awk
内から現在のシェルに変数を設定する方法はありますか?
ファイルに対して何らかの処理を行い、データを出力したいと思います。ファイル全体を読み通すので、行数(この場合はFNR
)を保存したいと思います。
FNR
値を使用してシェル変数を設定する方法を見つけることができないようですが、どうなりますか。そうでない場合は、出力ファイルからFNR
を読み取って、FNR
の値で_num_lines
_を設定する必要があります。
awk 'END{system(...)}'
を使用していくつかの組み合わせを試しましたが、機能するように管理できませんでした。これを回避する方法はありますか?
$ echo "$var"
$ declare $( awk 'BEGIN{print "var=17"}' )
$ echo "$var"
17
Evalの代わりにdeclareを使用する理由は次のとおりです。
$ eval $( awk 'BEGIN{print "echo \"removing all of your files, ha ha ha....\""}' )
removing all of your files, ha ha ha....
$ declare $( awk 'BEGIN{print "echo \"removing all of your files\""}' )
bash: declare: `"removing': not a valid identifier
bash: declare: `files"': not a valid identifier
最初のケースでは、evalはawkが出力する文字列を実行することに注意してください。これは偶然非常に悪いことです。
別の方法があります。
これは、変数のvaluesをsingle変数で取得し、分割したい場合に特に便利です。たとえば、変数を作成するデータベースの単一行の値のリストがあります。
val="hello|beautiful|world" # assume this string comes from a database query
read a b c <<< $( echo ${val} | awk -F"|" '{print $1" "$2" "$3}' )
echo $a #hello
echo $b #beautiful
echo $c #world
Readコマンドはパイプから読み取らず、代わりにstdinから読み取るため、「here string」、つまりこの場合は<<<が必要です。
サブシェルからその親シェルに変数をエクスポートすることはできません。ただし、次のような他の選択肢もあります。
AWKを使用してファイルの別のパスを作成してレコードをカウントし、コマンド置換を使用して結果をキャプチャします。例えば:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
を呼び出してカウントを取得できます。いくつかの答えが示唆するように、宣言を使用しようとする人への警告。
evalにはこの問題はありません。
宣言するために提供されたawk(または他の式)が空の文字列になる場合、declareは現在の環境をダンプします。これはほとんど間違いなくあなたが望むものではありません。
例:awkパターンが入力に存在しない場合、出力を印刷しないため、予期しない動作が発生します。
この例....
unset var
var=99
declare $( echo "foobar" | awk '/fail/ {print "var=17"}' )
echo "var=$var"
var=99
The current environment as seen by declare is printed
and $var is not changed
設定する値をawk変数に保存し、最後に出力する小さな変更により、これが解決されます。
unset var
var=99
declare $( echo "foobar" | awk '/fail/ {tmp="17"} END {print "var="tmp}' )
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
一致するパターンでこれが機能することを示すには
unset var
var=99
declare $( echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}' )
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
awk
で割り当てステートメントを出力します。
_MYVAR=NewValue
_
次に、シェルスクリプトで、eval
awk
スクリプトの出力:
_eval $(awk ....)
# then use $MYVAR
_
編集:人々はdeclare
の代わりにeval
を使用することを推奨します。これは、割り当て以外の何かが内部スクリプトによって出力された場合にエラーが発生しにくくなります。 bashのみですが、シェルis bashで、スクリプトに_#!/bin/bash
_が含まれていて、この依存関係が正しく記述されている場合は問題ありません。
eval $(...)
バリアントは広く使用されており、既存のプログラムはeval
に適した出力を生成しますが、declare
には適しません(lesspipe
は例です)。それがそれを理解することが重要である理由であり、bashのみのバリアントは「ローカライズされすぎています」。
ここまでですべてを合成するには、awkを使用して1行のファイルを読み取るスクリプトからシェル環境変数を設定するのに便利だと思うことを共有します。明らかに、必要な変数を見つけるために/pattern/
の代わりにNR==1
を使用できます。
# export a variable from a script (such as in a .dotfile)
declare $( awk 'NR==1 {tmp=$1} END {print "Shell_VAR=" tmp}' /path/to/file )
export Shell_VAR
これにより、declare
コマンドが引数なしで発行された場合の変数の大量出力、およびブラインドeval
のセキュリティリスクが回避されます。
echo(First arg:$ 1 "for((i = 0; i <$ 1; i ++)); echo "inside" echo "Welcome $ i times。" cat man.xml | awk '{x [NR] = $ 0} END {for(i = 2; i <= NR; i ++){if(x [i]〜//){x [i + 1] = "' $ i '" } print x [i]}} '> $ i.xml done echo "compleated"