Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

* lib/shellwords.rb: Add shellescape() and shelljoin().

* lib/shellwords.rb: Rename shellwords() to shellsplit() and make
  the former an alias to the latter.

* lib/shellwords.rb: Add escape(), split(), join() as class
  methods, which are aliases to their respective long names
  prefixed with `shell'.

* lib/shellwords.rb: Add String#shellescape(), String#shellsplit()
  and Array#shelljoin() for convenience.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
commit d2a68669da4b31f70d99888ef87286c6cc901afb 1 parent 068d11e
@knu knu authored
Showing with 141 additions and 18 deletions.
  1. +14 −0 ChangeLog
  2. +127 −18 lib/shellwords.rb
View
14 ChangeLog
@@ -1,3 +1,17 @@
+Tue Sep 11 17:25:59 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/shellwords.rb: Add shellescape() and shelljoin().
+
+ * lib/shellwords.rb: Rename shellwords() to shellsplit() and make
+ the former an alias to the latter.
+
+ * lib/shellwords.rb: Add escape(), split(), join() as class
+ methods, which are aliases to their respective long names
+ prefixed with `shell'.
+
+ * lib/shellwords.rb: Add String#shellescape(), String#shellsplit()
+ and Array#shelljoin() for convenience.
+
Mon Sep 10 15:48:31 2007 Tanaka Akira <akr@fsij.org>
* range.c: represent initialized state using EXCL instead of FL_USER3.
View
145 lib/shellwords.rb
@@ -1,31 +1,32 @@
#
-# shellwords.rb: Split text into an array of tokens a la UNIX shell
+# shellwords.rb: Manipulates strings a la UNIX Bourne shell
#
#
-# This module is originally a port of shellwords.pl, but modified to
-# conform to POSIX / SUSv3 (IEEE Std 1003.1-2001).
+# This module manipulates strings according to the word parsing rules
+# of the UNIX Bourne shell.
#
-# Examples:
+# The shellwords() function was originally a port of shellwords.pl,
+# but modified to conform to POSIX / SUSv3 (IEEE Std 1003.1-2001).
#
-# require 'shellwords'
-# words = Shellwords.shellwords(line)
-#
-# or
-#
-# require 'shellwords'
-# include Shellwords
-# words = shellwords(line)
+# Authors:
+# - Wakou Aoyama
+# - Akinori MUSHA <knu@iDaemons.org>
#
module Shellwords
-
#
- # Split text into an array of tokens in the same way the UNIX Bourne
- # shell does.
+ # Splits a string into an array of tokens in the same way the UNIX
+ # Bourne shell does.
+ #
+ # argv = Shellwords.split('here are "two words"')
+ # argv #=> ["here", "are", "two words"]
#
- # See the +Shellwords+ module documentation for an example.
+ # +String#shellsplit+ is a shorthand for this function.
#
- def shellwords(line)
+ # argv = 'here are "two words"'.shellsplit
+ # argv #=> ["here", "are", "two words"]
+ #
+ def shellsplit(line)
words = []
field = ''
line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
@@ -40,5 +41,113 @@ def shellwords(line)
words
end
- module_function :shellwords
+ alias shellwords shellsplit
+
+ module_function :shellsplit, :shellwords
+
+ class << self
+ alias split shellsplit
+ end
+
+ #
+ # Escapes a string so that it can be safely used in a Bourne shell
+ # command line.
+ #
+ # Note that a resulted string should be used unquoted and is not
+ # intended for use in double quotes nor in single quotes.
+ #
+ # open("| grep #{Shellwords.escape(pattern)} file") { |pipe|
+ # # ...
+ # }
+ #
+ # +String#shellescape+ is a shorthand for this function.
+ #
+ # open("| grep #{pattern.shellescape} file") { |pipe|
+ # # ...
+ # }
+ #
+ def shellescape(str)
+ # An empty argument will be skipped, so return empty quotes.
+ return "''" if str.empty?
+
+ str = str.dup
+
+ # Process as a single byte sequence because not all shell
+ # implementations are multibyte aware.
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
+
+ # A LF cannot be escaped with a backslash because a backslash + LF
+ # combo is regarded as line continuation and simply ignored.
+ str.gsub!(/\n/, "'\n'")
+
+ return str
+ end
+
+ module_function :shellescape
+
+ class << self
+ alias escape shellsplit
+ end
+
+ #
+ # Builds a command line string from an argument list +array+ joining
+ # all elements escaped for Bourne shell and separated by a space.
+ #
+ # open('|' + Shellwords.join(['grep', pattern, *files])) { |pipe|
+ # # ...
+ # }
+ #
+ # +Array#shelljoin+ is a shorthand for this function.
+ #
+ # open('|' + ['grep', pattern, *files].shelljoin) { |pipe|
+ # # ...
+ # }
+ #
+ def shelljoin(array)
+ array.map { |arg| shellescape(arg) }.join(' ')
+ end
+
+ module_function :shelljoin
+
+ class << self
+ alias join shelljoin
+ end
+end
+
+class String
+ #
+ # call-seq:
+ # str.shellsplit => array
+ #
+ # Splits +str+ into an array of tokens in the same way the UNIX
+ # Bourne shell does. See +Shellwords::shellsplit+ for details.
+ #
+ def shellsplit
+ Shellwords.split(self)
+ end
+
+ #
+ # call-seq:
+ # str.shellescape => string
+ #
+ # Escapes +str+ so that it can be safely used in a Bourne shell
+ # command line. See +Shellwords::shellescape+ for details.
+ #
+ def shellescape
+ Shellwords.escape(self)
+ end
+end
+
+class Array
+ #
+ # call-seq:
+ # array.shelljoin => string
+ #
+ # Builds a command line string from an argument list +array+ joining
+ # all elements escaped for Bourne shell and separated by a space.
+ # See +Shellwords::shelljoin+ for details.
+ #
+ def shelljoin
+ Shellwords.join(self)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.