FORループからawkに変数を渡して特定の単語を取得します。

FORループからawkに変数を渡して特定の単語を取得します。

テーブルの一部の単語をCSV形式のTXTファイルとして印刷しようとしています。

{...some code...}
number_lines=$(awk 'END { print NR }' Table1.txt
if [$number_lines -gt 5]
then
    for ((i=5; i<$number_lines; i++))
    do
       word=$(awk 'FNR==$i {print $2}' Table1.txt)
       echo $word
       printf "$variable1\t$variable2\t$variable3\t$word\n" >> Table2.csv
    done
fi

私はi $ 2行の単語を得ることができると思いましたが、FNR = = 5 {print $ 2}を使用して欲しいものを得ることができましたが、Table1.txtにいくつかの単語があるかどうかわからないので、何かが必要です。 from 行 5 から始まり (前の行は必要ないので) Table1.txt の行 -1 の終わりに移動します。私の貧しいコードが誰かを怒らせないことを願っています。私はこれを緊急にしなければならなかったし、以前はbashで何もしたことがなかったので申し訳ありません。

答え1

-v オプションを使用すると、シェル変数を awk 変数として非表示にできます。

awkコマンドは次のとおりです。

awk -v Seq="$i" 'FNR==Seq {print $2}' Table1.txt

その修正が提案されたら、10行すべてを単一のawkプログラムに置き換える方が速く、よりきれいになります。これにより、Table1に含まれるすべての行を読み取る必要がなくなります。 awkは行の計算とデータの読み取りに非常に堪能です。

テストされていませんが、「一部のコード」の後のすべての内容を次のように置き換えます。

awk -v Vars="${variable1}\t${variable2}\t${variable3}\t" \
    'FNR >= 5 { printf ("%s\n%s%s\n", $2, Vars, $2); }' \
    Table1.txt > Table2.csv

答え2

awkファイル全体を何度も読み取って処理するこのようなループで繰り返し実行したくありません(行数 - 4回)。

理想的には、すべての操作をawk(またはPerlやシェルではない言語)で実行する方が良いでしょう。しかし、変数に何があるのか​​、それとも変数がどのように定義されているのかわかりません$variable[123](ところで、おそらくbashでこれを行うには、次のようにする必要があります)。 、配列を使用) forループをwhile読み取りループに置き換える方法を紹介します。

while read r word ; do
  echo "$word"
  printf "$variable1\t$variable2\t$variable3\t$word\n" >> Table2.csv
done < <(awk 'NR > 4 {print $2}')

まだあまりありません(テキスト処理にシェル自体を使用することは決して良い考えではありません。)、しかし、少なくともawk一度だけ実行され、入力ファイルを一度だけ読み取る。

答え3

シェルループで繰り返しawkを呼び出す代わりに、awkを一度呼び出すことでこれを行う必要があります。これは非常に遅く、しっかりとコーディングするのが難しいからです。簡潔でテスト可能なサンプル入力と期待される出力を投稿すると、さらに役立つかもしれませんが、おそらく次のようなことをしたいと思います。

awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

たとえば、

$ variable1='this stuff'
$ variable2='other stuff'
$ variable3='last stuff'

$ cat Table1.txt
01      the     foo
02      quick   bar
03      brown   foo
04      fox     bar
05      jumped  foo
06      over    bar
07      the     foo
08      lazy    bar
09      dogs    foo
10      back    bar

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

$ cat Table2.csv
this stuff      other stuff     last stuff      jumped
this stuff      other stuff     last stuff      over
this stuff      other stuff     last stuff      the
this stuff      other stuff     last stuff      lazy
this stuff      other stuff     last stuff      dogs

$variableこれらのsのいずれかに拡張したくないエスケープシーケンス(リテラルタブ文字など)を含めることができる場合は、次のように\tします。

vars="$variable1"$'\t'"$variable2"$'\t'"$variable3" awk '
    BEGIN { vars=ENVIRON["vars"]; OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

バラよりawkスクリプトでシェル変数を使用する方法シェル変数の値を awk スクリプトに渡す方法に関する追加情報。

echo $wordシェルスクリプトでこの問題を解決してください。これがデバッグ印刷の場合、実際にはstdoutではなくstderrに移動する必要があります(つまり、で書く必要がありますecho "$word" >&2)。その後、awkスクリプトは次のようになります。

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev | "cat>&2"   # or print prev > "/dev/stderr" if your awk supports that
        print vars, prev
    }
    { prev = $2 }
' Table1.txt > Table2.csv

しかし、本当に標準出力にエクスポートしたい場合は、次のようにすることができます。

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev
        print vars, prev > "Table2.csv"
    }
    { prev = $2 }
' Table1.txt

または:

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev
        print vars, prev | "cat>&3"
    }
    { prev = $2 }
' Table1.txt 3> "Table2.csv"

関連情報