web-dev-qa-db-ja.com

引用符を使用するときに単一のバックスラッシュが表示されるのはなぜですか

二重引用符なしまたは二重引用符付きで使用する場合、bashはバックスラッシュを同じように扱うといつも思っていましたが、間違っていました。

[user@linux ~]$ echo "foo \ "
foo \
[user@linux ~]$ echo foo \ # Space after \
foo

したがって、二重引用符を使用すると、バックスラッシュは常に出力されると思いましたが、次のようになります。

[user@linux ~]$ echo "foo \" "
foo "
[user@linux ~]$ echo "foo \\ "
foo \

最初のコード行にバックスラッシュが表示されるのはなぜですか?

5
Motte001

セクション .1.2.3二重引用符GNU Bashマニュアル の説明:

バックスラッシュは、 '_$_'、 '_`_'、 '_"_'、 '_\_'、またはnewlineのいずれかの文字が続く場合にのみ、特別な意味を保持します。 。二重引用符内では、これらの文字のいずれかが後に続くバックスラッシュが削除されます。特別な意味のない文字の前のバックスラッシュは変更されません。二重引用符は、バックスラッシュを前に付けることにより、二重引用符で囲むことができます。有効にすると、二重引用符で囲まれた「_!_」がバックスラッシュを使用してエスケープされない限り、履歴の展開が実行されます。 「_!_」の前のバックスラッシュは削除されません。

したがって、二重引用符内の_\_は、単一引用符内の_\_および引用符外の_\_の両方とは異なる方法で処理されます。二重引用符で特別な意味を持つ可能性がある文字を文字どおりに処理する位置にある場合を除いて、文字どおりに処理されます。

_\'_、_\?_および_\*_であるため、_'_、_?_、_*_などのシーケンスは文字どおりに扱われ、バックスラッシュは削除されません。二重引用符で囲まれている場合、すでに特別な意味はありません。

9
Eliah Kagan

バックスラッシュの解釈はコンテキストによって異なります。

  • 二重引用符内(最初の例):

    The backslash  retains its special meaning  only when followed
    by one of the following characters: $, `, ", \, or <newline>.
    
  • 引用符なし(2番目の例):

    A  non-quoted  backslash  (\)  is the  escape  character.   It
    preserves  the  literal  value  of  the  next  character  that
    follows,  with the  exception of  <newline>.  If  a \<newline>
    pair  appears, and  the backslash  is not  itself quoted,  the
    \<newline> is treated  as a line continuation (that  is, it is
    removed from the input stream and effectively ignored).
    
  • 構成要素$'....'を使用します。引用符の内部では、Cとほぼ同じように、標準のバックスペース文字を使用できます。 \n\tなど.

  • バッククォートの使用:

    When  the old-style  backquote form  of substitution  is used,
    backslash retains its literal  meaning except when followed by
    $, `, or \.
    

引用のソース:bashマニュアル

5

ここに「理解のために複雑な」例があります。うまくいけば、クォートとバックスラッシュを理解しようとしている他の人にとって役立つでしょう。

この例では、パターンを3回繰り返します。

>~# echo 'ABC\n\t'
ABC\n\t

一重引用符を使用すると、かなり簡単です。

>~# echo 'ABC\n\t' | sed -e 's#ABC\\n\\t#ABC\\n\\tABC\\n\\tABC\\n\\t#'
                                  ↑  ↑      ↑        ↑  ↑     ↑  ↑
                    # These backslashes escaped by sed
ABC\n\tABC\n\tABC\n\t

二重引用符を使用してこれを行う方法は次のとおりです(ここでも、理解のためだけに複雑です)。

>~# echo 'ABC\n\t' | sed -e "s#ABC\\\n\\\t#$(printf '%0.sABC\\\\n\\\\t' $(seq 1 3))#"
                                  ↑   ↑                     ↑ ↑  ↑ ↑
            # These backslashes are removed in double quotes. Showing intermediate stage:

>~# echo 'ABC\n\t' | sed -e "s#ABC\\n\\t#$(printf '%0.sABC\\n\\t' $(seq 1 3))#"

                # Expanding printf results in:

>~# echo 'ABC\n\t' | sed -e 's#ABC\\n\\t#ABC\\n\\tABC\\n\\tABC\\n\\t#'

ABC\n\tABC\n\tABC\n\t

試してみて、引用符とバックスラッシュをマスターするには、printfの前後の一重引用符を二重引用符に置き換えます。

0