
これが私が今まで持っているものです:
#!/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
オプションを渡します。
答え2
これはどうですか?
$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1 PASS=tmmjXSWL
DB=drupal_2 USER=drupal2 PASS=FHiJSYHM
DB=drupal_3 USER=drupal3 PASS=b7bFNj06
DB=drupal_4 USER=drupal4 PASS=0AaV62EL
解決しなければならない問題があるのか、それとももっと理論的なものを知りたいのかはわかりません。