~のため

~のため

":"で区切られた値のリストがありますが、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

割り当て後のキーワードは認識されません。したがって(存在する場合)という一般的なコマンドを実行しますforIFS=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)は次のようになります。

  1. コマンドの最初の単語
  2. Case, for, in を除く予約語の 1 つの後の最初の単語
  3. ケースコマンドの3番目の単語(この場合にのみ有効)
  4. 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の「パス」機能を使用してください。コロンで区切られたリストと呼ばれる新しいデータ型を使用できますbashaddpath、、delpath待つ。listpathオフラインメディアを検索して一般的なタスクを実行するには、でこれらの機能を使用します。PATHMANPATHlocatebash

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

関連情報