Bashでは、トークン化はコマンドライン処理の1つのステップです。 Bashマニュアルから
シェルは$ IFSの各文字を区切り文字として扱い、これらの文字をフィールドの終端として使用して、他の拡張結果を単語に分割します。 IFSが設定されていない
<space><tab><newline>
場合、またはその値がデフォルト値の場合、前の<space>, <tab>, and <newline>
拡張結果の始まりと終わりのシーケンスは無視され、始まりまたは終わりにないIFS文字シーケンスは単語を区切るために使用されます。 IFSにデフォルト以外の値がある場合、スペース文字がIFS値(IFSスペース)にある限り、単語の先頭と末尾のスペースとタブのシーケンスは無視されます。 IFS スペースではなく、IFS のすべての文字と隣接する IFS スペース文字が一緒にフィールドを区別します。空白文字の IFS シーケンスも区切り文字と見なされます。 IFS値が空の場合、単語分割は発生しません。
space
パラメータ間の区切り文字がまたはで置き換えられるように、次の例を書き直したいと思いますa
。b
c
tab
newline
$ echo a b c
a b c
しかし、ボタンを押してもTab
何も起こりません。
をクリックすると、\
出力に、との間にスペースがありませんreturn
。a
b
c
$ echo a\
> b\
> c
abc
なぜ引用文で言うようにできないのですか?
しかし、何の結果も出ません$IFS
。
$ echo $IFS
答え1
bash
改行文字は値に関係なく特別に処理されますIFS
。改行前のバックスラッシュにより改行が発生します。無視される。これは、単語の分割に関係なく、IFS
一部のカスタム値に設定されている場合にも発生します。
からLESS=+/^QUOTING man bash
:
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).
改行文字で単語分割が異なる方法で発生することがわかります。つまり、改行文字を変数に入れてから、引用しないでecho
変数を参照します。
$ myvar=a$'\n'b$'\n'c
$ echo "$myvar"
a
b
c
$ echo $myvar
a b c
$
答え2
直接の答え
これ引用しないコマンド: 、それが何であれecho a b c
(メタ文字スペース)に分割されます。 :echoは次のように定義されているため、分割パラメータはスペースで印刷されます。IFS
echo
a
b
c
LESS=+/'^ *echo \[-neE\] \[arg ...\]' man bash
スペースで区切られた出力パラメーターとそれに続く改行文字が続きます。
参加もありません$IFS
。
したがって、あなたが引用した内容はここでは関係ありません。主な部分は次のとおりです。
...異なる拡張の結果を単語に分割...
あなた〜しなければならない$IFS
使用前の延長があります。
には拡張子がありませんa b c
。
$IFSの効果を使用する必要がある場合は、引用符なしの拡張機能を使用してください。
$ var='a b c'
$ echo $var
a b c
ただし、これはまだ$IFS
出力には使用されず、分割にのみ使用されます。
出力のIFS。
$IFS
の相関関係(出力について)はどこにありますか$*
?
$ set -- a b c
$ IFS=$'\t'
$ printf '%s\n' "$*" | od -An -vtx1c
61 09 62 09 63 0a
a \t b \t c \n
これはあなたに必要なものですか?
その他の事項
キーボードタブ
Tabキーを押しても何も起こりません
次に、を押してCtrlV手を離し、同時にを押しますTab。
ただし、引用符がないと、変数にタブ文字を割り当てることはできません。テスト:
$ var=a b ### The space represents a tab as above.
bash: b: command not found
必要になります。
$ var="a b" ### The space represents a tab as above.
少なくとも二重引用符です。
見積もりIFS
$ IFSの結果はありません。
$ echo $IFS
$IFS
参照がないため、何も生成されません$IFS
。努力する:
<user>$ echo "$IFS" | sed -n l
\t$
$
<user>$
$IFS
echoコマンドの新しい行とechoコマンドの新しい行があります。
printfに変更することをお勧めします。
<user>$ printf '%s' "$IFS" | sed -n l
\t$
<user>$
そしてodを使う:
$ printf '%s' "$IFS" | od -An -vtx1c
20 09 0a
\t \n
文字列にどの文字が含まれているかを「確認」する方法が既にあるためです。
また、これを使用して複数の文字列内の内容を「表示」することもできます。
$ var='a b c'
$ echo "$var" | od -An -vtx1c
61 20 62 20 63 0a
a b c \n
これは驚くべきことではありません。なぜなら、これは(一重引用符で)次のようにしてはいけません。
$ var='a\
> b\
> c'
$ echo "$var" | od -An -vtx1c
61 5c 0a 62 5c 0a 63 0a
a \ \n b \ \n c \n
正確に入力された内容です。 varが正しく引用されると、バックスラッシュが正しく表示されます。
引用する
ただし、二重引用符で引用すると、一部の文字が変更されることがあります。
$ var="a\
> b\
> c"
$ echo "$var" | od -An -vtx1c
61 62 63 0a
a b c \n
しかし、あなたが書いた内容には、var設定やエコーで使用することに関する引用はありません。
これはシェルにとってはいけないことです。お願いします正しい引用。
答え3
スペースをタブに置き換えるには、$IFS
パラメータ配列を使用できます。
unset IFS
set a b c
IFS=$(printf \\t)
printf "%s\n" "$*"
これが$IFS
分割に関連していることを理解してください。これには、リストのコンテキストを分割するためにシェルが使用する引用符のない拡張文字のリストが含まれています。君はそれを本当に使えないじゃない変える特殊シェルパラメータの特別な場合を除く文字です$*
。他のすべてのケースでは、その使用は次のとおりです。無効引用符で囲まれていないシェル拡張の特定の部分を明確にして区別します。