[英]Function with awk to print single or multiple columns
我經常使用awk
選擇單列,並在了解了別名后開始使用
alias a1='awk '\{print $1}'\'
alias a2='awk '\{print $2}'\'
...
學到更多知識后,我認為這些很俗氣,並以代替
function a() {
awk "{print \$$1}"
}
因此,現在我可以a 3
或a 11
而無需創建顯式別名。
這樣很好,但是有時候我需要選擇多個列,並且當我這樣做時,我不得不訴諸於實際的完整awk '{print ...}'
命令(恐怖!)。
因此,我試圖提出一種與a
函數相似的方法,但可以接受不同數量的參數,因此我可以執行a 3
或a 5 7
或a 2 4 9
。
我已經嘗試過使用$@
和$*
但無法正確處理,現在我嘗試的所有內容都是俗氣的解決方法,因此我寧願停下來詢問如何以正確的方式進行操作。
謝謝大家
您可能會因這種事情而變得任意復雜(如果您希望能夠說出a 2-5 7 11-
,就像cut
?),但是這將適用於數字列表:
a() { (IFS=,; awk '{print '"${*/#/$}"'}'); }
這需要一些解釋。
a() { ... }
定義一個shell函數 ,它在各種方面都不同於別名,其中之一就是您可以為其指定參數。
在shell函數中,我想更改IFS
的值; 為了避免必須記住舊值並將其改回,我在實際要執行的命令周圍加上了(...)
,這使它在子shell中執行。 子外殼完成后,所有環境更改都隨之完成,因此可以有效地將更改更改為IFS
本地。
IFS
是用於單詞拆分的字符集,但是它也定義了在用引號引起來的"$*"
擴展(即函數或腳本參數的列表)中用於分隔元素的字符。 因此,將其設置為,
意味着$*
擴展名將是一個逗號分隔的列表。
我要創建的awk程序實際上類似於{print $1,$4,$7}
,因此除了在列表之間添加逗號之外,我還需要在每個數字前添加$
。 我使用bash
參數擴展替代語法: ${parameter/pattern/replacement}
做到這一點。 通過指定*
作為參數,我得到$*
並將替換應用於每個參數。 (請注意,引號用引號引起來。如果沒有,將無法使用。)
在替換表達式中,模式為空,因為模式開頭的#
字符表示匹配項必須位於字符串的開頭。 由於實際模式為空,因此第一個匹配項始終位於字符串的開頭,因此替換( $
)將插入每個參數的開頭。 之所以需要#
是因為//
在語法上是不同的:它的意思是“更改所有出現的模式”,而不僅僅是第一個。
與許多語言不同,在bash中,搜索和替換表達式不是以/
終止,而是以匹配的}
終止。 如果鍵入${p/foo/bar/}
,它將用bar/
替換foo
的第一個實例。
$ cat tst.sh
function a {
awk -v args="$*" '
BEGIN { n=split(args,f) }
{ for (i=1;i<=n;i++) printf "%s%s", $(f[i]), (i<n?OFS:ORS) }
'
}
echo "a b c d e f" | a 1 3 5
echo "---"
echo "a b c d e f" | a 1 3 4 6
$ ./tst.sh
a c e
---
a c d f
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.