有沒有辦法在awk
以內的當前shell中設置變量?在awk的當前shell中設置變量
我想對一個文件進行一些處理,並打印出一些數據;因爲我會讀整個文件,所以我想節省行數 - 在這種情況下,FNR
。
偏偏雖然我似乎無法找到一種方法來設置與FNR
值shell變量;如果不是這樣的話,我必須從我的輸出文件中讀取FNR
,以設置num_lines
,其值爲FNR
。
我一直在使用awk 'END{system(...)}'
嘗試了一些組合,但不能管理它的工作。任何方式在這個?
有沒有辦法在awk
以內的當前shell中設置變量?在awk的當前shell中設置變量
我想對一個文件進行一些處理,並打印出一些數據;因爲我會讀整個文件,所以我想節省行數 - 在這種情況下,FNR
。
偏偏雖然我似乎無法找到一種方法來設置與FNR
值shell變量;如果不是這樣的話,我必須從我的輸出文件中讀取FNR
,以設置num_lines
,其值爲FNR
。
我一直在使用awk 'END{system(...)}'
嘗試了一些組合,但不能管理它的工作。任何方式在這個?
$ echo "$var"
$ declare $(awk 'BEGIN{print "var=17"}')
$ echo "$var"
17
這也是爲什麼你應該使用聲明的,而不是EVAL:
$ 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打印第一種情況下,這可能會意外地是一個非常糟糕的事情!
讓awk
打印出來的賦值語句:
MYVAR=NewValue
然後在你的shell腳本,eval
您awk
腳本的輸出:
eval $(awk ....)
# then use $MYVAR
編輯:人建議使用declare
代替eval
,如果內部腳本打印的是分配以外的內容,則稍微不太容易出錯。它只是bash而已,但是當shell 爲 bash且腳本具有#!/bin/bash
時,可以正確指出此依賴關係。
eval $(...)
變體被廣泛使用,現有的程序產生適合eval
的輸出,但不適用於declare
(lesspipe
是一個例子);這就是爲什麼理解它很重要的原因,而且僅限bash的變體是「太本地化」的。
您無法將變量從子shell導出到其父shell。你有一些其他的選擇,不過,包括:
請使用AWK來計算記錄文件的另一個通,並用命令替換來捕獲結果。例如:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
,讓您的計數。這是另一種方法。
時,當你有值的變量的在單變量,你想拆起來這是非常有用的。例如,您可以從數據庫中的單行中獲取要創建變量的值列表。
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 abc <<< $ var」中一樣。謝謝 –
<3 ..感謝。 – calbertts
有一點需要提一下,如果字段之間用空格隔開,可以簡化爲: ''' read abc < << $(echo $ {val}) ''' –
警告任何人試圖使用聲明爲而不是讀由幾個答案建議。
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讀取單行文件的腳本設置shell環境變量。顯然/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
的安全風險發出。
+1,但只要是我編寫代碼,使用'eval'我就沒有多大的問題了。 – Rubens
@Rubens,直到你意外地做壞事的那一天。如果您現在習慣於編寫安全代碼,您將來不會被咬。 –
@glennjackman +1感謝您的提示;我想這就是爲什麼在這裏考慮安全編碼的原因(: – Rubens