Bashスクリプトでタブ区切りのファイルを繰り返します。

Bashスクリプトでタブ区切りのファイルを繰り返します。

これが私が今まで持っているものです:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

入力ファイルの例:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

そしてスクリプトの出力は次のようになります。

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

何らかの理由で、各変数は行全体に設定されます。echo users.txt | cut -f1コマンドラインで使用すると、トークンは正常に返されます。

ベストアンサー1

問題はコマンドにありますecho $line。周囲に引用符がないため、$lineシェルは単語分割を実行し、各単語をワイルドカードパターンとして解釈します。試してみてください

a='*.txt foo'
ls $a

あなたの場合、タブは単語を分離してから別の引数になりますecho。このechoコマンドは、引数をスペースで区切って印刷します。したがって、cutタブで区切られたフィールドの代わりにスペースで区切られたフィールドを受け取ります。

$foo変数の置換とコマンドの置換には常に二重引用符を使用してください。$(foo)(なぜ除外するのか、なぜそれができるのか理解していない限り)echo "$line"ここではうまくいきますが、提案したタスクを実行する複雑な方法です。

シェルで構文解析方法を維持することで、コマンドにread入力をフィールドとして解析させることができます。

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

read変数の値を文字で区切られたフィールドに分割しますIFS。このフィールドは、デフォルトでは空白とタブ(1行には表示できない改行を含む)で構成されています。タブに分割するには、まずIFS単一のタブに設定します。先行および末尾のタブ文字は無視され、連続したタブ文字は 1 つのタブ文字として扱われます。

read特殊文字として扱われます\。バックスラッシュの後に改行文字が続くと、\\単一のバックスラッシュになります。この動作を回避するには、この-rオプションを渡します。

おすすめ記事