Shellwords 模組

操作字串,就像 UNIX Bourne shell

這個模組會根據 UNIX Bourne shell 的字詞剖析規則來操作字串。

shellwords() 函式最初是 shellwords.pl 的移植,但已修改為符合 IEEE Std 1003.1-2008, 2016 Edition [1] 的 Shell & Utilities 卷。

用法

您可以使用 Shellwords 將字串剖析成 Bourne shell 友善的 Array

require 'shellwords'

argv = Shellwords.split('three blind "mice"')
argv #=> ["three", "blind", "mice"]

在您需要 Shellwords 後,您可以使用 split 別名 String#shellsplit

argv = "see how they run".shellsplit
argv #=> ["see", "how", "they", "run"]

它們將引號視為特殊字元,因此不匹配的引號將導致 ArgumentError

argv = "they all ran after the farmer's wife".shellsplit
     #=> ArgumentError: Unmatched quote: ...

Shellwords 也提供執行相反操作的方法。 Shellwords.escape 或其別名 String#shellescape 會為命令列使用而跳脫字串中的 shell 元字元。

filename = "special's.txt"

system("cat -- #{filename.shellescape}")
# runs "cat -- special\\'s.txt"

請注意「–」。如果沒有它,當 cat(1) 的引數以「-」開頭時,它會將其視為命令列選項。 Shellwords.escape 保證會將字串轉換成 Bourne shell 會將其剖析回原始字串的格式,但程式設計師有責任確保將任意引數傳遞給命令時不會造成損害。

Shellwords 也附帶 Array 的核心擴充套件 Array#shelljoin

dir = "Funny GIFs"
argv = %W[ls -lta -- #{dir}]
system(argv.shelljoin + " | less")
# runs "ls -lta -- Funny\\ GIFs | less"

您可以使用這個方法從引數陣列建構完整的命令列。

作者

連絡人

資源

1: IEEE Std 1003.1-2008, 2016 Edition, the Shell & Utilities volume

常數

VERSION

公共類別方法

escape(str)
別名為:shellescape
join(array)
別名為:shelljoin
shellescape(str) 按一下以切換來源

跳脫字串,以便可以在 Bourne shell 命令列中安全使用。str 可以是非字串物件,它會回應 to_s

請注意,結果字串應使用未加引號,且不打算用於雙引號或單引號中。

argv = Shellwords.escape("It's better to give than to receive")
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"

String#shellescape 是此函式的簡寫。

argv = "It's better to give than to receive".shellescape
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"

# Search files in lib for method definitions
pattern = "^[ \t]*def "
open("| grep -Ern -e #{pattern.shellescape} lib") { |grep|
  grep.each_line { |line|
    file, lineno, matched_line = line.split(':', 3)
    # ...
  }
}

呼叫者有責任使用此字串所用 shell 環境的正確編碼編碼字串。

多位元組字元會視為多位元組字元處理,而不是位元組。

如果 str 的長度為零,則會傳回一個空的引號 String

# File lib/shellwords.rb, line 150
def shellescape(str)
  str = str.to_s

  # An empty argument will be skipped, so return empty quotes.
  return "''".dup if str.empty?

  str = str.dup

  # Treat multibyte characters as is.  It is the caller's responsibility
  # to encode the string in the right encoding for the shell
  # environment.
  str.gsub!(/[^A-Za-z0-9_\-.,:+\/@\n]/, "\\\\\\&")

  # A LF cannot be escaped with a backslash because a backslash + LF
  # combo is regarded as a line continuation and simply ignored.
  str.gsub!(/\n/, "'\n'")

  return str
end
別名為:escape
shelljoin(array) 按一下以切換來源

從引數清單 array 建立命令列字串。

所有元素都結合到一個單一字串中,欄位以空白分隔,其中每個元素都針對 Bourne shell 跳脫,並使用 to_s 字串化。

ary = ["There's", "a", "time", "and", "place", "for", "everything"]
argv = Shellwords.join(ary)
argv #=> "There\\'s a time and place for everything"

Array#shelljoin 是此函式的捷徑。

ary = ["Don't", "rock", "the", "boat"]
argv = ary.shelljoin
argv #=> "Don\\'t rock the boat"

您也可以在元素中混用非字串物件,如 Array#join 所允許。

output = `#{['ps', '-p', $$].shelljoin}`
# File lib/shellwords.rb, line 196
def shelljoin(array)
  array.map { |arg| shellescape(arg) }.join(' ')
end
別名為:join
shellsplit(line) 按一下以切換來源

以與 UNIX Bourne shell 相同的方式將字串分割成陣列中的代幣。

argv = Shellwords.split('here are "two words"')
argv #=> ["here", "are", "two words"]

不過,請注意,這不是命令列剖析器。除了單引號、雙引號和反斜線之外,Shell 元字元不會被視為元字元。

argv = Shellwords.split('ruby my_prog.rb | less')
argv #=> ["ruby", "my_prog.rb", "|", "less"]

String#shellsplit 是此函式的捷徑。

argv = 'here are "two words"'.shellsplit
argv #=> ["here", "are", "two words"]
# File lib/shellwords.rb, line 90
def shellsplit(line)
  words = []
  field = String.new
  line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
    |word, sq, dq, esc, garbage, sep|
    raise ArgumentError, "Unmatched quote: #{line.inspect}" if garbage
    # 2.2.3 Double-Quotes:
    #
    #   The <backslash> shall retain its special meaning as an
    #   escape character only when followed by one of the following
    #   characters when considered special:
    #
    #   $ ` " \ <newline>
    field << (word || sq || (dq && dq.gsub(/\\([$`"\\\n])/, '\\1')) || esc.gsub(/\\(.)/, '\\1'))
    if sep
      words << field
      field = String.new
    end
  end
  words
end
別名為:shellwordssplit
shellwords(line)
別名為:shellsplit
split(line)
別名為:shellsplit

私人實例方法

shellescape(str) 按一下以切換來源

跳脫字串,以便可以在 Bourne shell 命令列中安全使用。str 可以是非字串物件,它會回應 to_s

請注意,結果字串應使用未加引號,且不打算用於雙引號或單引號中。

argv = Shellwords.escape("It's better to give than to receive")
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"

String#shellescape 是此函式的簡寫。

argv = "It's better to give than to receive".shellescape
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"

# Search files in lib for method definitions
pattern = "^[ \t]*def "
open("| grep -Ern -e #{pattern.shellescape} lib") { |grep|
  grep.each_line { |line|
    file, lineno, matched_line = line.split(':', 3)
    # ...
  }
}

呼叫者有責任使用此字串所用 shell 環境的正確編碼編碼字串。

多位元組字元會視為多位元組字元處理,而不是位元組。

如果 str 的長度為零,則會傳回一個空的引號 String

# File lib/shellwords.rb, line 150
def shellescape(str)
  str = str.to_s

  # An empty argument will be skipped, so return empty quotes.
  return "''".dup if str.empty?

  str = str.dup

  # Treat multibyte characters as is.  It is the caller's responsibility
  # to encode the string in the right encoding for the shell
  # environment.
  str.gsub!(/[^A-Za-z0-9_\-.,:+\/@\n]/, "\\\\\\&")

  # A LF cannot be escaped with a backslash because a backslash + LF
  # combo is regarded as a line continuation and simply ignored.
  str.gsub!(/\n/, "'\n'")

  return str
end
別名為:escape
shelljoin(array) 按一下以切換來源

從引數清單 array 建立命令列字串。

所有元素都結合到一個單一字串中,欄位以空白分隔,其中每個元素都針對 Bourne shell 跳脫,並使用 to_s 字串化。

ary = ["There's", "a", "time", "and", "place", "for", "everything"]
argv = Shellwords.join(ary)
argv #=> "There\\'s a time and place for everything"

Array#shelljoin 是此函式的捷徑。

ary = ["Don't", "rock", "the", "boat"]
argv = ary.shelljoin
argv #=> "Don\\'t rock the boat"

您也可以在元素中混用非字串物件,如 Array#join 所允許。

output = `#{['ps', '-p', $$].shelljoin}`
# File lib/shellwords.rb, line 196
def shelljoin(array)
  array.map { |arg| shellescape(arg) }.join(' ')
end
別名為:join
shellsplit(line) 按一下以切換來源

以與 UNIX Bourne shell 相同的方式將字串分割成陣列中的代幣。

argv = Shellwords.split('here are "two words"')
argv #=> ["here", "are", "two words"]

不過,請注意,這不是命令列剖析器。除了單引號、雙引號和反斜線之外,Shell 元字元不會被視為元字元。

argv = Shellwords.split('ruby my_prog.rb | less')
argv #=> ["ruby", "my_prog.rb", "|", "less"]

String#shellsplit 是此函式的捷徑。

argv = 'here are "two words"'.shellsplit
argv #=> ["here", "are", "two words"]
# File lib/shellwords.rb, line 90
def shellsplit(line)
  words = []
  field = String.new
  line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
    |word, sq, dq, esc, garbage, sep|
    raise ArgumentError, "Unmatched quote: #{line.inspect}" if garbage
    # 2.2.3 Double-Quotes:
    #
    #   The <backslash> shall retain its special meaning as an
    #   escape character only when followed by one of the following
    #   characters when considered special:
    #
    #   $ ` " \ <newline>
    field << (word || sq || (dq && dq.gsub(/\\([$`"\\\n])/, '\\1')) || esc.gsub(/\\(.)/, '\\1'))
    if sep
      words << field
      field = String.new
    end
  end
  words
end
別名為:shellwordssplit
shellwords(line)
別名為:shellsplit