ユーザーリストを含むCSVがあり、各ユーザーに一意でランダムに生成されたワンタイムパスワードを含む列を追加したいと思います。
私のスクリプトはうまくいきますが、引き続き行を追加し続けます。変数を設定するためにコードをループから移動すると正常に動作しますが、すべてのユーザーは同じパスワードを取得します。
最後の行で終了するにはどうすればよいですか?
#!/bin/bash
#add column to csv
ORIG_FILE="new-users2.csv"
NEW_FILE="Output.csv"
{ echo `head -1 $ORIG_FILE`",One Time Password" ; tail -n +2 $ORIG_FILE | \
while read x ; OneTimePass=$(openssl rand -base64 14 | head -c 6) ; do echo "$x,$OneTimePass" ; done ; } > $NEW_FILE
ベストアンサー1
ループ構文がwhile...do...done
正しくありません。あなたはこれを実行しています:
while read x ; OneTimePass=$(openssl rand -base64 14 | head -c 6) ; do ...
キーワードの見積もり形式while
は以下に説明されていますhelp while
。
$ help while
while: while COMMANDS; do COMMANDS; done
Execute commands as long as a test succeeds.
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
Exit Status:
Returns the status of the last command executed.
ここでは2つのコマンドを提供します。read x ;
そして、OneTimePass=$(openssl rand -base64 14 | head -c 6)
2番目のコマンドは常に機能し、いつでもコマンドを再実行できるため、シャットダウンはありませんopenssl
。そのため、while
ループは終了せず、さらに多くの行を作成します。あなたが追求するのはこれです:
while read x; do
something
done
以下は、正しい引用符や変数名の大文字の使用を防ぐなど、他のいくつかの改善点を含む作業バージョンのスクリプトです。
#!/bin/bash
#add column to csv
orig_file="new-users2.csv"
new_file="Output.csv"
printf "%s,%s\n" "$(head -1 "$orig_file")" "One Time Password" > "$new_file"
tail -n +2 "$orig_file" |
while read -r x; do
OneTimePass="$(openssl rand -base64 14 | head -c 6)"
printf '%s,%s\n' "$x" "$OneTimePass"
done >> "$new_file"
個人的には、ファイル名をハードコーディングすることはスクリプトを使いにくくして使いやすさを落とすので避けたいと思います。入力ファイル名を引数として取り、stdout で印刷することで、目的の出力ファイルを選択できます。
#!/bin/bash
#add column to csv
orig_file=$1
printf "%s,%s\n" "$(head -1 "$orig_file")" "One Time Password"
tail -n +2 "$orig_file" |
while read -r x; do
OneTimePass="$(openssl rand -base64 14 | head -c 6)"
printf '%s,%s\n' "$x" "$OneTimePass"
done
その後、次のように実行できます。
foo.sh new-users2.csv > Output.csv
次の入力ファイルでテストしました。
$ cat new-users2.csv
name,age
Bob,45
Alice,36
結果:
$ foo.sh new-users2.csv
name,age,One Time Password
Bob,45,BTkLQW
Alice,36,CzQa4U