入力のN列ごとに出力

入力のN列ごとに出力

開始列、増分値、およびファイル名をランタイム・パラメーターとして渡して、ファイル内のすべてのN列を印刷するスクリプトを作成しようとしています。以下は私のスクリプトです。

file=$1
st=$2
inc=$3

echo $file
echo $st
echo $inc

awk '{for (i = $st; i <= NF; i += $inc) printf ("%s%c", $i, i + $inc <= NF ? " " : "\n");}' $file

結果が得られません。誰でも私を助けることができますか?私の入力は次のようになります。script.sh file_name 1 4

よろしくお願いします。 :-)

答え1

シェル変数は自動的に変数になりませんawk(変数はthフィールドではないとマークされてawkいます)。シェル変数をに渡す場合は、簡単な方法は環境を使用することです。var$varvarawk

#! /bin/sh -
file=$1
ST=$2
INC=$3

export ST INC
awk '
  {
    sep = ""
    for (i = ENVIRON["ST"]; i <= NF; i += ENVIRON["INC"]) {
      printf "%c%s", sep, $i
      sep = OFS
    }
    printf "\n"
  }' < "$file"

シェル変数を引用し、任意のファイル名を引数として使用しないでください(一部はaまたは特別に呼び出されたファイル名awkとして扱うため)。=-

変数を渡すもう1つの方法は、awkawkスクリプトの後に-v awkvar="$shellvar"またはパラメータを使用することです。ただし、エスケープシーケンスが拡張され(改行文字など)、GNU 4.2以降awkvar="$shellvar"では任意の文字列と一緒に使用することはできません。\\\\nawkで始まり@/終わる値は/特別に扱われます。POSIXモードを除いて。

awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc)...}' < "$file"

または

awk  '{for (i = st; i <= NF; i += inc)...}' st="$st" inc="$inc" < "$file"

この変数には数字のみが含まれるので(バックスラッシュはありません)、ここでは問題ありません。

何をしてもしないでください。

awk 'for (i = '"$st"'; i <= NF; i += '"$inc"')...'

言及する必要がない

awk 'for (i = '$st'; i <= NF; i += '$inc')...'

つまり、シェルがに渡されたコードの値と変数を拡張するようにします$st。これにより、コマンド注入の脆弱性(たとえば、次の値)が発生する可能性があります。$incawkstsystem("reboot")

答え2

あなたのスクリプトを修正し、今動作します。 2つのエラーがあります。 (a)シェル変数を手動でawkに渡す必要があります(これは構文を使用して実行されます)。(b)変数を表すためにそれを使用しない-v awk_var="$shell_var"でください。シンボルはフィールド位置にのみ使用されます。$$

file=$1
st=$2
inc=$3

echo $file
echo $st
echo $inc

awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc) printf ("%s%c", $i, i + inc <= NF ? " " : "\n");}' $file

関連情報