From d2a68669da4b31f70d99888ef87286c6cc901afb Mon Sep 17 00:00:00 2001 From: knu Date: Tue, 11 Sep 2007 08:27:48 +0000 Subject: * 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 --- lib/shellwords.rb | 145 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 127 insertions(+), 18 deletions(-) (limited to 'lib/shellwords.rb') 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 # 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 -- cgit v1.2.3