":"で区切られた値のリストがありますが、1つずつ処理したいと思います。
区切り文字が空白の場合は問題ありません。
nuclear@korhal:~$ for a in 720 500 560 130; do echo $a; done
720
500
560
130
しかし、IFS(Internal Field Separator)を次のように設定した後、奇妙なことが発生し始めました。
nuclear@korhal:~$ IFS=":" for a in 720:500:560:130; do echo $a; done;
bash: syntax error near unexpected token `do'
IFSを設定するときにすべてのセミコロンをスキップする場合:
nuclear@korhal:~$ IFS=":" for a in 720:500:560:130 do echo $a done;
Command 'for' not found, did you mean:
command 'vor' from deb vor (0.5.8-1)
command 'fop' from deb fop (1:2.5-1)
command 'tor' from deb tor (0.4.4.5-1)
command 'forw' from deb mailutils-mh (1:3.9-3.2)
command 'forw' from deb mmh (0.4-2)
command 'forw' from deb nmh (1.7.1-7)
command 'sor' from deb pccts (1.33MR33-6build1)
command 'form' from deb form (4.2.1+git20200217-1)
command 'fox' from deb objcryst-fox (1.9.6.0-2.2)
command 'fort' from deb fort-validator (1.4.0-1)
command 'oor' from deb openoverlayrouter (1.3.0+ds1-3)
Try: sudo apt install <deb name>
Bashはforコマンドをまったく認識しません。この場合、IFSが設定されていない場合はより多くの出力が必要になるため、プロンプトが表示されます(通常の動作)。
IFSをカスタム文字に設定するとどうなりますか? forループが機能しないのはなぜですか?
私はKubuntu 20.10 Bashバージョン5.0.17を使用しています。
答え1
割り当て後のキーワードは認識されません。したがって(存在する場合)という一般的なコマンドを実行しますfor
。IFS=blah for ...
for
$ cat > ./for
#!/bin/sh
echo script for
$ chmod +x ./for
$ PATH=$PATH:.
$ for x in a b c
> ^C
$ foo=bar for x in a b c
script for
ただし、Bashは実行前に入力行全体を解析するため、このキーワードはdo
その前に構文エラーを発生させます。
これは、割り当ての代わりにリダイレクトを使用するのと似ています。 複合コマンドの前にリダイレクト入力を指定できますか?そしてまた見たwhileループの入力リダイレクト演算子の順序を変更できないのはなぜですか?文法の定義方法の詳細。
また見なさい:bash forループで一時的な環境変数を使用する方法は?
私のZshはもっと厳しいです。
$ zsh -c 'foo=bar for x in a b c'
zsh:1: parse error near `for'
ただし、Zshは複合コマンドの前にリダイレクトを許可します。これにより、次の3行が出力されますtest.txt
。
$ zsh -c '> test.txt for x in a b c ; do echo $x; done '
また、IFS
静的文字列の分割には使用されません。たとえば、720:500:560:130
トークン化は拡張でのみ機能します。だから:
$ IFS=":"
$ for a in 720:500:560:130; do echo "$a"; done;
720:500:560:130
しかし、
$ IFS=":"
$ s=720:500:560:130
$ for a in $s; do echo "$a"; done;
720
500
560
130
答え2
~のため
〜のようにPOSIXの要件特定の単語(含むfor
)は次のようになります。
- コマンドの最初の単語
- Case, for, in を除く予約語の 1 つの後の最初の単語
- ケースコマンドの3番目の単語(この場合にのみ有効)
- forコマンドの3番目の単語(この場合はinとdoのみが有効です)
ここでは状況が異なります。これがfor
シェルがエラーを理解して報告できない理由です。
一時 IFS に関するこの質問は、以下に関連しています。フィールド分割にはいつ一時的な IFS を使用できますか?。ただし、その答えは単純なコマンドにのみ適用されます(複合コマンドです)。
また:
IFS
IFSの価値はただ影響を与える拡大する(変数拡張).
IFS値を適用するには、前のコマンドで設定する必要があります。
$ a="one:two:three"
$ echo $a
one:two:three
$ (
> IFS=":"
> echo $a
> )
one two three
$ ( IFS=":"; echo $a )
one two three
しかし、いいえ:
$ ( IFS=":" echo $a )
one:two:three
これを行うには、コマンドの実行を遅らせる必要があります。
$ ( IFS=":" eval echo '$a' )
one two three
したがって、スクリプトに対して次のことを行う必要があります。
b="720:500:560:130"
( IFS=":";
for a in $b ;
do echo "$a" ;
done
)
拡張は引用されていないため、$b
すべてのglob文字(*、[、?、およびextglobセットを含む他の文字)も拡張されます。たぶん1つだけを生成するのではなく、ファイルのリストを生成することもできます。
答え3
IFSの魔法と戦うのではなく、Stephen Collyerの「パス」機能を使用してください。コロンで区切られたリストと呼ばれる新しいデータ型を使用できますbash
。addpath
、、delpath
待つ。listpath
オフラインメディアを検索して一般的なタスクを実行するには、でこれらの機能を使用します。PATH
MANPATH
locate
bash
AskUbuntuに対する私の答えは次のとおりです。
私は2000年にLinux Journalで説明されているStephen Collyerのbash_path_funcsを使います。
https://www.linuxjournal.com/article/3645 https://www.linuxjournal.com/article/376 8 https://www.linuxjournal.com/article/3935
addpath
この関数は、最初にそのエントリがパスに存在しない場合にのみパスにエントリを追加します。delpath -n
パスに存在しないディレクトリを削除します。
pathfunc.tgz
からファイルを受け取ることができます。https://web.archive.org/web/20061210054813/http://www.netspinner.co.uk:80/Downloads/pathfunc.tgz