代码之家  ›  专栏  ›  技术社区  ›  Red Cricket

我的sed命令和引号怎么了?[副本]

  •  0
  • Red Cricket  · 技术社区  · 8 年前

    alias 比如:

    alias rxvt='urxvt'
    

    效果很好。

    alias rxvt='urxvt -fg '#111111' -bg '#111111''
    

    不会起作用,也不会:

    alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
    

    那么,一旦转义了引号,如何在字符串中匹配开始和结束引号呢?

    alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
    

    看起来很难看,尽管如果允许这样连接它们,它将代表相同的字符串。

    0 回复  |  直到 7 年前
        1
  •  1378
  •   Craig Gidney Mihai    10 年前

    如果您真的想在最外层使用单引号,请记住,您可以粘合这两种引号。例子:

     alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
     #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
     #                     12345       12345     12345       1234
    

    如何解释 '"'"' ' :

    1. ' 结束使用单引号的第一个引号。
    2. " 用双引号开始第二个引号。
    3. 引用字符。
    4. 用双引号结束第二个引号。
    5. ' 用单引号开始第三个引号。

    如果不在(1)和(2)之间或(4)和(5)之间放置任何空格,shell将把该字符串解释为一个长单词。

        2
  •  251
  •   jan-glx charlie    8 年前

    我总是用序列替换每个嵌入的单引号: '\''


    我经常在Perl脚本中创建一个“quotify”函数来帮我完成这项工作。步骤如下:

    s/'/'\\''/g    # Handle each embedded quote
    $_ = qq['$_']; # Surround result with single quotes.
    

    当你介绍别人时,生活会变得更有趣 eval 进入你的外壳脚本。你必须重新引用所有的东西!

    例如,创建一个名为quotify的Perl脚本,其中包含上述语句:

    #!/usr/bin/perl -pl
    s/'/'\\''/g;
    $_ = qq['$_'];
    

    $ quotify
    urxvt -fg '#111111' -bg '#111111'
    

    结果:

    'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    

    然后可以将其复制/粘贴到alias命令中:

    alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    

    (如果需要将命令插入eval,请再次运行quotify:

     $ quotify
     alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    

    'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
    

    可复制/粘贴到评估:

    eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
    
        3
  •  181
  •   thiagowfx    8 年前

    自从巴什 2.04 语法 $'string' (而不是仅仅 'string' ;警告:不要与 $('string') )是另一个允许 ANSI C-like escape sequences

    简单示例:

      $> echo $'aa\'bb'
      aa'bb
    
      $> alias myvar=$'aa\'bb'
      $> alias myvar
      alias myvar='aa'\''bb'
    

    就你而言:

    $> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
    $> alias rxvt
    alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    

    常见转义序列按预期工作:

    \'     single quote
    \"     double quote
    \\     backslash
    \n     new line
    \t     horizontal tab
    \r     carriage return
    

    以下是复制并粘贴的相关文档 man bash (版本4.4):

    形式为$'string'的单词将被特别处理。单词扩展为字符串,反斜杠转义字符按ANSI C标准替换。反斜杠转义序列(如果存在)解码如下:

        \a     alert (bell)
        \b     backspace
        \e
        \E     an escape character
        \f     form feed
        \n     new line
        \r     carriage return
        \t     horizontal tab
        \v     vertical tab
        \\     backslash
        \'     single quote
        \"     double quote
        \?     question mark
        \nnn   the eight-bit character whose value is the octal 
               value nnn (one to three digits)
        \xHH   the eight-bit character whose value is the hexadecimal
               value HH (one or two hex digits)
        \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
               the hexadecimal value HHHH (one to four hex digits)
        \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
                   is the hexadecimal value HHHHHHHH (one to eight 
                   hex digits)
        \cx    a control-x character
    

    扩大后的结果是单引号,似乎美元符号没有出现。


    见 Quotes and escaping: ANSI C like strings "Bash Changes" 文件( overview here )对于与 $'字符串'

    根据unix.stackexchange.com How to use a special character as a normal one? 它应该在bash、zsh、mksh、ksh93、FreeBSD和busybox sh中工作(有一些变体)。

        4
  •  49
  •   Gringo Suave    12 年前

    gnu reference manual :

    (')保留 引号中的每个字符。一个 单引号,即使前面有 反斜杠。

    alias x='y \'z '

    alias x="echo \'y "
    > x
    > 'y
    
        5
  •  29
  •   Mathias Bynens    13 年前

    我可以确认使用 '\'' 'A '\''B'\'' C' (这里所有的引号都是单引号)。如果传递给echo,它将打印以下内容: A 'B' C . 在每个 '\'' 第一个引号关闭当前的单引号字符串,如下所示 \' 将一个引号粘到上一个字符串上( \'

        6
  •  17
  •   leftaroundabout    8 年前

    这两个版本都可以工作,要么使用转义单引号字符(\')进行连接,要么将单引号字符括在双引号(“')中进行连接。

    alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
               │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
               └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                          ┊┊         ┊┊       ┊┊         ┊┊│
                          ┊┊         ┊┊       ┊┊         ┊┊│
                          └┴─────────┴┴───┰───┴┴─────────┴┘│
                              All escaped single quotes    │
                                                           │
                                                           ?
    

    正如您在前面的ASCII/Unicode艺术中看到的,最后一个转义的单引号(\')后面跟着一个不必要的单引号(')。使用像Notepad++中的语法高亮器可以证明是非常有用的。

    另一个例子也是如此,如下所示:

    alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
    alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'
    

    $ cat Little_Commas.TXT
    201737194
    201802699
    201835214
    
    $ rc Little_Commas.TXT
    201737194, 201802699, 201835214
    
        7
  •  16
  •   kenorb    11 年前

    shell中转义引号的简单示例:

    $ echo 'abc'\''abc'
    abc'abc
    $ echo "abc"\""abc"
    abc"abc
    

    完成了,已经打开了一个( ' \' ),然后打开另一个( ). 此语法适用于所有命令。这和第一个答案非常相似。

        8
  •  15
  •   nicerobot    9 年前

    rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }
    

    你可以称之为:

    rxvt 123456 654321
    

    我们的想法是,您现在可以将其命名,而不必考虑引号:

    alias rxvt='rxvt 123456 654321'
    

    # 出于某种原因,在所有通话中:

    rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }
    

    你可以称之为:

    rxvt '#123456' '#654321'
    

    当然,别名是:

    alias rxvt="rxvt '#123456' '#654321'"
    

    (哎呀,我想我确实是在引用:)

        9
  •  10
  •   Rob Jens    11 年前

    我只是用外壳代码。。例如 \x27 或 \\x22

        10
  •  9
  •   Abbas Gadhia    10 年前

    由于不能将单引号放在单引号字符串中,所以最简单、最可读的选项是使用HEREDOC字符串

    command=$(cat <<'COMMAND'
    urxvt -fg '#111111' -bg '#111111'
    COMMAND
    )
    
    alias rxvt=$command
    

    在上面的代码中,HEREDOC被发送到 cat 命令及其输出通过命令替换符号分配给变量 $(..)

    $()

        11
  •  6
  •   Kyle Rose    10 年前

    这些答案大多是针对你所问的具体案例。我和一位朋友开发了一种通用方法,允许在需要通过多层shell扩展(例如,通过ssh)引用bash命令时任意引用, su -c , bash -c

    quote_args() {
        local sq="'"
        local dq='"'
        local space=""
        local arg
        for arg; do
            echo -n "$space'${arg//$sq/$sq$dq$sq$dq$sq}'"
            space=" "
        done
    }
    

    这正是它所说的:它shell分别引用每个参数(当然,在bash扩展之后):

    $ quote_args foo bar
    'foo' 'bar'
    $ quote_args arg1 'arg2 arg2a' arg3
    'arg1' 'arg2 arg2a' 'arg3'
    $ quote_args dq'"'
    'dq"'
    $ quote_args dq'"' sq"'"
    'dq"' 'sq'"'"''
    $ quote_args "*"
    '*'
    $ quote_args /b*
    '/bin' '/boot'
    

    它对一层膨胀有明显的作用:

    $ bash -c "$(quote_args echo a'"'b"'"c arg2)"
    a"b'c arg2
    

    (注意 $(quote_args ...) 巴什-c )并且它可以更普遍地用于通过多层扩展正确地报价:

    $ bash -c "$(quote_args bash -c "$(quote_args echo a'"'b"'"c arg2)")"
    a"b'c arg2
    

    1. shell将每个参数引到内部 quote_args 然后分别将结果输出与内部双引号组合为一个参数。
    2. 空壳引号 bash -c ,以及步骤1中已被引用的结果,然后将结果与外部双引号组合为一个参数。
    3. 巴什-c .

    简而言之,这是个主意。你可以用这个做一些非常复杂的事情,但是你必须小心计算的顺序和引用的子字符串。例如,以下行为是错误的(对于“错误”的某些定义):

    $ (cd /tmp; bash -c "$(quote_args cd /; pwd 1>&2)")
    /tmp
    $ (cd /tmp; bash -c "$(quote_args cd /; [ -e *sbin ] && echo success 1>&2 || echo failure 1>&2)")
    failure
    

    quote_args cd /; pwd 1>&2 分成两个独立的命令, quote_args cd / 和 pwd 1>&2 ,所以CWD仍然 /tmp pwd 执行命令。第二个例子说明了globbing的一个类似问题。实际上,所有bash扩展都会出现相同的基本问题。这里的问题是,命令替换不是函数调用:它实际上是在评估一个bash脚本,并将其输出用作另一个bash脚本的一部分。

    如果试图简单地转义shell运算符,则会失败,因为结果字符串传递给 只是一系列单独引用的字符串,这些字符串不会被解释为运算符,这很容易看出您是否回显了传递给bash的字符串:

    $ (cd /tmp; echo "$(quote_args cd /\; pwd 1\>\&2)")
    'cd' '/;' 'pwd' '1>&2'
    $ (cd /tmp; echo "$(quote_args cd /\; \[ -e \*sbin \] \&\& echo success 1\>\&2 \|\| echo failure 1\>\&2)")
    'cd' '/;' '[' '-e' '*sbin' ']' '&&' 'echo' 'success' '1>&2' '||' 'echo' 'failure' '1>&2'
    

    问题是你的报价太高了。您需要的是将运算符取消引号,作为封闭的输入 巴什-c ,这意味着他们需要在 $(引用参数…) 命令替换。

    因此,在最一般的意义上,您需要做的是对命令替换时不打算单独展开的命令的每个字进行shell引用,并且不对shell运算符应用任何额外的引用:

    $ (cd /tmp; echo "$(quote_args cd /); $(quote_args pwd) 1>&2")
    'cd' '/'; 'pwd' 1>&2
    $ (cd /tmp; bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")
    /
    $ (cd /tmp; echo "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
    'cd' '/'; [ -e *'sbin' ] && 'echo' 'success' 1>&2 || 'echo' 'failure' 1>&2
    $ (cd /tmp; bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
    success
    

    完成此操作后,整个字符串对于进一步引用任意级别的求值是公平的:

    $ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")"
    /
    $ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")"
    /
    $ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")")"
    /
    $ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")"
    success
    $ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *sbin ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")"
    success
    $ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")")"
    success
    

    等。

    这些例子似乎过于夸张了 success , sbin ,和 不需要引用shell,但是在编写带有任意输入的脚本时要记住的关键点是,要引用所有不确定的内容 不 需要引用,因为您永远不知道用户何时将 Robert'; rm -rf / .

    为了更好地了解封面下的内容,您可以使用两个小助手函数:

    debug_args() {
        for (( I=1; $I <= $#; I++ )); do
            echo -n "$I:<${!I}> " 1>&2
        done
        echo 1>&2
    }
    
    debug_args_and_run() {
        debug_args "$@"
        "$@"
    }
    

    $ debug_args_and_run echo a'"'b"'"c arg2
    1:<echo> 2:<a"b'c> 3:<arg2> 
    a"b'c arg2
    
    $ bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)"
    1:<echo> 2:<a"b'c> 3:<arg2> 
    a"b'c arg2
    
    $ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")"
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
    1:<echo> 2:<a"b'c> 3:<arg2> 
    a"b'c arg2
    
    $ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")"
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
    1:<echo> 2:<a"b'c> 3:<arg2> 
    a"b'c arg2
    
    $ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")")"
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'bash'"'"' '"'"'-c'"'"' '"'"''"'"'"'"'"'"'"'"'debug_args_and_run'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'echo'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'a"b'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'c'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'arg2'"'"'"'"'"'"'"'"''"'"''> 
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
    1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
    1:<echo> 2:<a"b'c> 3:<arg2> 
    a"b'c arg2
    
        12
  •  6
  •   teknopaul    10 年前

    真正的答案是,不能在单引号字符串中转义单引号。

    这是不可能的。

    如果我们假设我们在使用bash。

    Enclosing characters in single quotes preserves the literal value of each
    character within the quotes.  A single quote may not occur
    between single quotes, even when preceded by a backslash.
    

    您需要使用其他字符串转义机制之一“或\

    没有什么神奇的 alias 这就要求它使用单引号。

    alias rxvt="urxvt -fg '#111111' -bg '#111111'"
    alias rxvt=urxvt\ -fg\ \'#111111\'\ -bg\ \'#111111\'
    

    后者使用\转义空格字符。

    111111也不需要单引号。

    以下选项与其他两个选项获得相同的结果,因为rxvt别名可以按预期工作。

    alias rxvt='urxvt -fg "#111111" -bg "#111111"'
    alias rxvt="urxvt -fg \"#111111\" -bg \"#111111\""
    

    alias rxvt="urxvt -fg \#111111 -bg \#111111"
    
        13
  •  4
  •   oberlies Jochen Ehret    12 年前

    在给定的示例中,只使用双引号而不是单引号作为外部转义机制:

    alias rxvt="urxvt -fg '#111111' -bg '#111111'"
    

    这种方法适用于许多只想向命令传递固定字符串的情况:只需检查shell将如何通过 echo ,并在必要时用反斜杠转义字符。

    $ echo "urxvt -fg '#111111' -bg '#111111'"
    urxvt -fg '#111111' -bg '#111111'
    
        14
  •  3
  •   PatchyFog    12 年前

    以下是对上述一个真实答案的阐述:

    有时我会通过ssh使用rsync下载,并且必须在文件名中转义两次'!(天啊!)一次用于bash,一次用于ssh。在这里,交替使用引号分隔符的原理也是一样的。

    例如,假设我们想得到:路易斯·塞鲁克斯的洛杉矶故事。。。

    1. 首先,将Louis Theroux括在bash的单引号和ssh的双引号中:
    2. 然后使用单引号来转义双引号“
    3. 然后重复#2,使用单引号转义双引号“
    4. 然后将LA Stories括在bash的单引号和ssh的双引号中:“LA Stories”

    rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'
    

    对一个孩子来说,这是一项非常艰巨的工作,但是你可以

        15
  •  3
  •   JasonWoof    7 年前
    shell_escape () {
        printf '%s' "'${1//\'/\'\\\'\'}'"
    }
    

    实施说明:

    • 双引号,这样我们可以轻松地输出包装单引号并使用 ${...} 语法

    • bash的搜索和替换看起来像: ${varname//search/replacement}

    • ' 具有 '\''

    • '\'' ' 就像这样:

      1. '

      2. \' 编码 ' (反斜杠是必需的,因为我们不在引号内)

      3. 重新开始单引号

      4. bash自动连接字符串,字符串之间没有空格

    • 有一个 \ 在每 和 ' 因为这是 ${...//.../...} .

    string="That's "'#@$*&^`(@#'
    echo "original: $string"
    echo "encoded:  $(shell_escape "$string")"
    echo "expanded: $(bash -c "echo $(shell_escape "$string")")"
    

    P、 总是编码为单引号字符串,因为它们比双引号字符串简单得多。

        16
  •  2
  •   Eric Leschinski Mr. Napik    11 年前

    你想把太多的东西塞进太小的空间,所以使用bash函数。

    lets_do_some_stuff() {
        tmp=$1                       #keep a passed in parameter.
        run_your_program $@          #use all your passed parameters.
        echo -e '\n-------------'    #use your single quotes.
        echo `date`                  #use your back ticks.
        echo -e "\n-------------"    #use your double quotes.
    }
    alias foobarbaz=lets_do_some_stuff
    

    然后,您可以使用$1和$2变量、单引号、双引号和反勾号,而不用担心别名函数会破坏它们的完整性。

    el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
    alien Dyson ring detected @grid 10385
    -------------
    Mon Oct 26 20:30:14 EDT 2015
    -------------
    
        17
  •  2
  •   wisbucky Ishan    8 年前

    显然,简单地用双引号括起来会更容易些,但其中的挑战在哪里呢?这是只使用单引号的答案。我用变量代替 alias 别名 .

    $ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
    $ echo $rxvt
    urxvt -fg '#111111' -bg '#111111'
    

    关键是,你可以关闭单引号,并重新打开它的次数,因为你想。例如 foo='a''b' 与 foo='ab' \' ,然后重新打开下一个单引号。

    故障图

    这个图表通过使用括号来显示单引号的打开和关闭位置,使之更加清晰。引号不是像圆括号那样的“嵌套”。您还可以注意正确应用的颜色突出显示。引用的字符串是栗色的,而 \' 是黑色的。

    'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'    # original
    [^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^    # show open/close quotes
     urxvt -fg   ' #111111  '  -bg   ' #111111  '    # literal characters remaining
    

        18
  •  2
  •   Ole Tange    7 年前

    如果安装了GNU Parallel,则可以使用其内部引用:

    $ parallel --shellquote
    L's 12" record
    <Ctrl-D>
    'L'"'"'s 12" record'
    $ echo 'L'"'"'s 12" record'
    L's 12" record
    

    --shellquote 多次:

    $ parallel --shellquote --shellquote --shellquote
    L's 12" record
    <Ctrl-D>
    '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
    $ eval eval echo '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
    L's 12" record
    

    它将引用所有支持的shell中的字符串(不仅是 bash ).

        19
  •  1
  •   user2350426 user2350426    10 年前

    此函数:

    quote () 
    { 
        local quoted=${1//\'/\'\\\'\'};
        printf "'%s'" "$quoted"
    }
    

    ' 里面 ' . 使用如下:

    $ quote "urxvt -fg '#111111' -bg '#111111'"
    'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    

    #!/bin/bash
    
    quote ()
    {
        local quoted=${1//\'/\'\\\'\'};
        printf "'%s'" "$quoted"
    }
    
    while read line; do
        quote "$line"
    done <<-\_lines_to_quote_
    urxvt -fg '#111111' -bg '#111111'
    Louis Theroux's LA Stories
    'single quote phrase' "double quote phrase"
    _lines_to_quote_
    

    将输出:

    'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
    'Louis Theroux'\''s LA Stories'
    ''\''single quote phrase'\'' "double quote phrase"'
    

    所有在单引号中正确引用的字符串。

        20
  •  1
  •   George V. Reilly    9 年前

    #!/usr/bin/env python
    
    from __future__ import print_function
    
    try:  # py3
        from shlex import quote as shlex_quote
    except ImportError:  # py2
        from pipes import quote as shlex_quote
    
    s = """foo ain't "bad" so there!"""
    
    print(s)
    print(" ".join([shlex_quote(t) for t in s.split()]))
    

    这将输出:

    foo ain't "bad" so there!
    foo 'ain'"'"'t' '"bad"' so 'there!'
    
        21
  •  1
  •   ジョージ    6 年前

    这是我的两分钱--如果有人想的话 sh bash -特定的(但是,解决方案效率不高,因为它启动了一个外部程序-- sed ):

    • 把这个放进去 quote.sh (或者只是 quote PATH :
    # this works with standard input (stdin)
    quote() {
      echo -n "'" ;
      sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g' ;
      echo -n "'"
    }
    
    case "$1" in
     -) quote ;;
     *) echo "usage: cat ... | quote - # single-quotes input for Bourne shell" 2>&1 ;;
    esac
    
    

    例如:

    $ echo -n "G'day, mate!" | ./quote.sh -
    'G'"'"'day, mate!'
    

    当然,这也会让你回头:

    $ echo 'G'"'"'day, mate!'
    G'day, mate!
    

    说明: 基本上我们必须用引号将输入括起来 ' '"'"' (以配对结束开头的报价 ,用双引号将找到的单引号括起来-- "'" ,然后最后发布新的开场单引号 ' ' + "'" + ' == '"'"'

    一个标准的方法就是 塞德

    s/\(['][']*\)/'"\1"'/g 
    

    不过,一个小问题是,为了在shell中使用它,需要在sed表达式本身中转义所有这些单引号字符——这会导致

    sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g' 
    

    (构建此结果的一个好方法是提供原始表达式 s/\(['][']*\)/'"\1"'/g 凯尔·罗斯或乔治·雷利的剧本)。

    最后,期望输入来自 stdin --因为通过命令行参数传递它可能已经太麻烦了。

    ./quote.sh --help 想知道它能做什么。)

        22
  •  0
  •   exbuddha    10 年前

    这是另一个解决方案。此函数将接受一个参数,并使用单引号字符对其进行适当的引号,正如上面的投票答案所解释的:

    single_quote() {
      local quoted="'"
      local i=0
      while [ $i -lt ${#1} ]; do
        local ch="${1:i:1}"
        if [[ "$ch" != "'" ]]; then
          quoted="$quoted$ch"
        else
          local single_quotes="'"
          local j=1
          while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
            single_quotes="$single_quotes'"
            ((j++))
          done
          quoted="$quoted'\"$single_quotes\"'"
          ((i+=j-1))
        fi
        ((i++))
      done
      echo "$quoted'"
    }
    

    single_quote "1 2 '3'"
    '1 2 '"'"'3'"'"''
    
    x="this text is quoted: 'hello'"
    eval "echo $(single_quote "$x")"
    this text is quoted: 'hello'
    
    推荐文章