3

bash変数を からに渡す方法に関するいくつかの質問を見つけましawk-v

スクリプトの外で、私が実行しているコマンドは

awk '$2 ~ /^\/var$/ { print $1 }' /etc/fstab

パーティションだけを検索/etc/fstab/var、物理マウント ポイントを出力するか、存在しない場合は何も出力しません。

スクリプト内には、多数のパーティションを含む配列があり、その配列を繰り返し処理して、各物理マウント ポイントの fstab を検索します。問題は、配列内の要素に a が含まれているという事実にあり/ます。

だから私がやりたいことは(恐ろしく間違ったawkで)次のとおりです。

PARTITIONS=(/usr /home /var tmp);
for ((n=0; n<${#PARTITION[@]}; n++)); do
    cat /etc/fstab | awk '$2 ~ /^\${PARTITIONS[$n]}$/ { print $1 }';
done

しかし、それが正しくないことはわかっています。私が今持っている最も近いものは次のとおりです。

PARTITIONS=(/usr /home /var tmp);
for ((n=0; n<${#PARTITION[@]}; n++)); do
    cat /etc/fstab | awk -v partition="${PARTITIONS[$n]}" '$2 ~ /^\/var$/ { print $1," ",partition }';
done

少なくとも、パーティション変数をawkに取得しますが、それを一致させるのにまったく役立ちません。

したがって、基本的には、配列をフィードして、物理パーティションを元に戻す必要があります。結果は最終的に別の配列に割り当てられますが、出力を取得したら、そこから移動できます。

また、最初は awk が猫の必要性を取り除くことができることも理解していますが、それを行うにはまだ awk について十分に知りません。:)

助けてくれてありがとう。

編集

cat /etc/fstab | awk -v partition="${PARTITIONS[$n]}" '$2 ~ partition { print $1 }'

有用であるために必要なものを概算します。どうやら正規表現を含めることに集中しすぎていたようです。他の誰かがこれをきれいにすることができれば、それは大歓迎です:)

4

6 に答える 6

2

配列全体をawkthrough-vに渡すこともできます。これは、ディレクトリ名にスペースが含まれていないことを前提としています。

PARTITIONS=(/usr /home /var /tmp)
awk -v partition="${PARTITIONS[*]}" \
  '$2 != "" && partition ~ $2"\\>" { print $1 }' /etc/fstab

forこれにより、ループが不要になります。

説明

  • `partition="${PARTITIONS[*]}" は、配列全体をスペースで区切られた文字列として渡します。
  • $2 != ""空行が一致しないことを意味します。
  • partition ~ $2"\\>"$2渡された文字列に一致\\>します。一致が単語の末尾にある必要があります。
于 2012-07-14T20:37:32.797 に答える
2
awk -v partition="${partitions[$n]}" '$2 ~ "^/" partition "$" { print $1 }' /etc/fstab

正規表現文字 ( ^- 文字列の先頭と$- 文字列の末尾) と、パーティション名の一部であるスラッシュとパーティション名を含む変数を、互いに隣接して配置することで連結できます。ハードコーディングされた正規表現を区切るスラッシュを使用する必要はありません。

AWK は、ファイル名catをパイプしたり<リダイレクトしたりすることなく、ファイル名を引数として受け入れます。

シェルや環境変数と名前が衝突する可能性を避けるために、シェル内で混合または小文字の変数名を使用することを習慣としてお勧めします。

于 2012-07-14T20:19:56.790 に答える
1

bash のプロセス置換を使用して、配列を追加のファイルとして awk に渡すことができます。

partitions=( /usr /home /var /tmp )
awk '
    FNR==NR { partitions[$0]=""; next } 
    $1 !~ /^#/ && ($2 in partitions) { print $1 }
' <(printf '%s\n' "${partitions[@]}") /etc/fstab

NR は現在読み取られているレコード (行) の数を保持し、FNR は現在のファイルで読み取られている現在のレコード数を保持するため、FNR==NR は最初のファイルを読み取るときにのみ真になります。これがこの場合のプロセス置換です。したがって、最初のファイルのパーティション配列を埋めます。

次に、2 番目のファイルについて、2 番目のフィールドが配列内にあるかどうかを確認します...

ただし、この場合は bash (バージョン >= 4.0) を使用します。これ/etc/fstabは通常、かなり小さいためです。

declare -A 'partitions=([/usr]= [/home]= [/var]= [/tmp]=)'
while read -r spec file vfstype mntops freq passno; do
    [[ $spec != \#* && ${partitions[$file]+set} ]] && echo "$spec"
done < /etc/fstab

または、実際の目標に応じて、 を解析dfして、ディレクトリがどのファイルシステムにあるかを知ることができます。

dirs=( /usr /home /var /tmp )
for dir in "${dirs[@]}"; do
    { read -r; read -r part _; } < <(df -P "$dir")
    echo "$part"
done
于 2012-07-14T20:35:32.100 に答える
1

まず、最も面倒なこと (GUoC) を取り除くために、awkは と同じようcatにファイルを操作できるので、直接渡すだけです。unflattenedを介して配列全体を渡すことはできませんが-v、アイテムを繰り返し処理しているため、問題ありません。回避したい場合は-v、bash 変数を awk スクリプトに直接含めることで渡すことができます。引用符 (空白と awk 独自の $variable の使用) に注意する必要があります。例:

awk '$2 ~ "'${PARTITIONS[$n]}'" { print $1 }' /etc/fstab

または、ソフトクォートを使用したより複雑なバージョン:

awk "\$2 ~ /${PARTITIONS[$n]//\//\\/}/ { print \$1 }" /etc/fstab
于 2012-07-14T20:11:41.243 に答える
0

次のように実行できます。

awk -v partitions="${PARTITIONS[*]}" '
    BEGIN { split(partitions,a," ") }
    { for (e in a) { if ($2 ~ a[e]) { print $1 } } }' /etc/fstab 

forそのため、外部でサイクルを作成する必要がなく、awkプロセスが少なくなります。

于 2012-07-14T20:10:29.783 に答える
0

ここに役立つかもしれないいくつかの観察があります。

入力が単一のファイルである場合は、何もする必要はありませんcat。あれは:

$ cat file | program # would normally just be ...
$ program < file

複雑なものを にフィードする必要がある場合はawk(1)、おそらくcat x | y... のようなユースケースがあります ...

(echo StartFlag ${PARTITIONS[*]}; cat /etc/fstab) | awk ...

そして最後に、SOで最良の結果を得るには、次のような形式で質問してください...

  1. 私の PARTITIONS bash 変数には、簡略化されたサンプル コンテンツが含まれています
  2. /etc/fstab に単純化された例の fstabが含まれているとします。
  3. 次の出力を取得するにはどうすればよいですか:単純化された入力に基づく正確な目的の出力
  4. これは私が試したことです:一部の人々はコードを提供するだけでなく、解決策に到達しようとした特定のプログラミングの問題について支援を求めるのに役立ちます
于 2012-07-14T20:12:07.677 に答える