簡體   English   中英

使用awk來打印單列或多列

[英]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 3a 11而無需創建顯式別名。

這樣很好,但是有時候我需要選擇多個列,並且當我這樣做時,我不得不訴諸於實際的完整awk '{print ...}'命令(恐怖!)。

因此,我試圖提出一種與a函數相似的方法,但可以接受不同數量的參數,因此我可以執行a 3a 5 7a 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM