シェルスクリプトの競合時の入力変数とパイプ変数

シェルスクリプトの競合時の入力変数とパイプ変数

次のスクリプトがあります。

#!/bin/bash
cat $1.txt | awk "{cmd=\"pwgen 10 1\"; cmd | getline pass; print substr($0, 1, length($0) -1) \">> ~/dresses/whole-dresses-shape/$1-\" pass \".jpg\"; close(cmd);}" | bash

コマンド内では、awk "{}"変数$0は現在読んでいる行を参照する必要がありますcat $1.txt。ただし、スクリプトファイル内で使用すると、$0実行中のファイル名の値が使用されます。

この例では、関数に出力substr()を取得させるにはどうすればよいですか?cat

必須ワークフロー:

  • ユーザー入力./myscript.sh hello
  • $1hello貴重な
  • 読み取った各行は、cat現在表示されている内容に割り当てられます。 $0

答え1

これはもう少しきれいにするためのいくつかの方法です(+文字列接続のprintf代わりにinを使用するprintことは個人的な好みの問題です。この場合はもっと読みやすくなります)。

  1. $1awk配列exの値をエクスポートして使用しますENVIRON

    #!/bin/bash
    
    export var="$1"
    
    cat "$1.txt" | awk '
      BEGIN{cmd="pwgen 10 1"} 
      {
        cmd | getline pass; 
        printf "%s >> ~/dresses/whole-dresses-shape/%s-%s.jpg\n", substr($0, 1, length($0) -1), ENVIRON["var"], pass;
        close(cmd);
      }
    '
    
  2. コマンドラインオプションを使用してex値を-v渡します。$1

    #!/bin/bash
    
    cat "$1.txt" | awk -v var="$1" '
      BEGIN{cmd="pwgen 10 1"} 
      {
        cmd | getline pass; 
        printf "%s >> ~/dresses/whole-dresses-shape/%s-%s.jpg\n", substr($0, 1, length($0) -1), var, pass;
        close(cmd);
      }
    '
    

どちらも外部の「滑らかな」引用符を「ハード」引用符に置き換えます。付随的な利点は、保護したい場合は参照レイヤーをオフにすることです。出力トークン化された文字列(おそらく良い習慣です。結果をシェルに明確にパイプしているため)。

printf "\"%s\" >> ~\"/dresses/whole-dresses-shape/%s-%s.jpg\"\n"

-vvs.についての議論のENVIRONために

答え2

このように:

variable="but put shell variable in double quotes"

echo 'Put most of the awk script in single quotes so that $s are not expanded, '"$variable"', then continue in single quotes.'

しかし、プログラムにコードを挿入する方法についての@Paul_Pedantのコメントを読んでください。

答え3

awkは一重引用符を使用します。未検証

#!/bin/bash
cat $1.txt | awk '{cmd="pwgen 10 1"; cmd | getline pass; print substr($0, 1, length($0) -1) ">> ~/dresses/whole-dresses-shape/'$1'-" pass ".jpg"; close(cmd);}' | bash

関連情報