summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-09-11 08:27:48 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-09-11 08:27:48 +0000
commitd2a68669da4b31f70d99888ef87286c6cc901afb (patch)
treea6caf6189d27f408a4ff42fd50c7b603235f82d2 /lib
parent068d11ef96ba506e3606713d431ce053e5e8294b (diff)
downloadruby-d2a68669da4b31f70d99888ef87286c6cc901afb.tar.gz
* 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
Diffstat (limited to 'lib')
-rw-r--r--lib/shellwords.rb145
1 files changed, 127 insertions, 18 deletions
diff --git a/lib/shellwords.rb b/lib/shellwords.rb
index 04d0c4fff8..ff1474b4e8 100644
--- a/lib/shellwords.rb
+++ b/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 @@ module Shellwords
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