我有幾行文字。我想使用 awk 提取特定單詞后的數字。
我嘗試了以下代碼,但它不起作用。
首先,通過以下方式創建測驗檔案:vi test.text. 有 3 列(這 3 個欄位是由其他一些使用 awk 的管道命令生成的)。
Index AllocTres CPUTotal
1 cpu=1,mem=256G 18
2 cpu=2,mem=1024M 16
3 4
4 cpu=12,gres/gpu=3 12
5 8
6 9
7 cpu=13,gres/gpu=4,gres/gpu:ret6000=2 20
8 mem=12G,gres/gpu=3,gres/gpu:1080ti=1 21
請注意,此檔案中有幾個空欄位。我想要實作的只是保留第一 部分之后的數字并使用管道gres/gpu洗掉所有cpu=和部分:輸出 3 列:mem=cat test.text | awk '{some_commands}'
Index AllocTres CPUTotal
1 18
2 16
3 4
4 3 12
5 8
6 9
7 4 20
8 3 21
uj5u.com熱心網友回復:
第一種解決方案:使用您顯示的示例,請嘗試遵循 GNUawk代碼。這會處理欄位之間的空間。
awk '
FNR==1{ print; next }
match($0,/[[:space:]] /){
space=substr($0,RSTART,RLENGTH-1)
}
{
match($2,/gres\/gpu=([0-9] )/,arr)
match($0,/^[^[:space:]] [[:space:]] [^[:space:]] ([[:space:]] )/,arr1)
space1=sprintf("%"length($2)-length(arr[1])"s",OFS)
if(NF>2){ sub(OFS,"",arr1[1]);$2=space arr[1] space1 arr1[1] }
}
1
' Input_file
上述代碼的輸出將如下所示,示例如下:
Index AllocTres CPUTotal
1 18
2 16
3 4
4 3 12
5 8
6 9
7 4 20
8 3 21
第二種解決方案:如果您不關心空格,請嘗試以下awk代碼。
awk 'FNR==1{print;next} match($2,/gres\/gpu=([0-9] )/,arr){$2=arr[1]} 1' Input_file
說明: 為上述代碼添加詳細說明。
awk ' ##Starting awk program from here.
FNR==1{ ##Checking condition if this is first line then do following.
print ##Printing current line.
next ##next will skip all further statements from here.
}
match($2,/gres\/gpu=([0-9] )/,arr){ ##using match function to match regex gres/gpu= digits and keeping digits in capturing group.
$2=arr[1] ##Assigning 1st value of array arr to 2nd field itself.
}
1 ##printing current edited/non-edited line here.
' Input_file ##Mentioning Input_file name here.
uj5u.com熱心網友回復:
使用sed
$ sed 's~\( \ \)[^,]*,\(gres/gpu=\([0-9]\)\|[^ ]*\)[^ ]* \ ~\1\3 \t\t\t\t ~' input_file
Index AllocTres CPUTotal
1 18
2 16
3 4
4 3 12
5 8
6 9
7 4 20
8 3 21
uj5u.com熱心網友回復:
awk '
FNR>1 && NF==3 {
n = split($2, a, ",")
for (i=1; a[i] !~ /gres\/gpu=[0-9] ,?/ && i<=n; i);
sub(/.*=/, "", a[i])
$2 = a[i]
}
NF==2 {$3=$2; $2=""}
{printf "%-7s%-11s%s\n",$1,$2,$3}' test.txt
輸出:
Index AllocTres CPUTotal
1 18
2 16
3 4
4 3 12
5 8
6 9
7 4 20
8 3 21
您可以根據需要調整列寬。
這假設第一列和最后一列總是有一個值,因此可以使用 NF(欄位數)來識別欄位 2。然后如果欄位 2 不為空,則用逗號分割該欄位,掃描結果陣列以查找第一個匹配項of gres/gpu,去掉這個后綴,列印三個欄位。如果欄位 2 為空,則倒數第二行插入一個空的 awk 欄位,因此printf始終有效。
如果上面的假設是錯誤的,也可以通過它的字符索引來識別欄位 2。
uj5u.com熱心網友回復:
一個awk基于解決方案而不需要
- array splitting,
- regex back-referencing,
- prior state tracking, or
- input multi-passing
—- since m.p. for /dev/stdin would require state tracking
|
{mng}awk '!_~NF || sub("[^ ] $", sprintf("%*s&", length-length($!(NF=NF)),_))' \
FS='[ ][^ \\/]*gres[/]gpu[=]|[,: ][^= ] [=][^,: ] ' OFS=
Index AllocTres CPUTotal
1 18
2 16
3 4
4 3 12
5 8
6 9
7 4 20
8 3 21
如果您不關心 nawk,那么它甚至是更簡單的單通方法,sub()每行只有 1 個包羅萬象的呼叫:
awk ' sub("[^ ]*$", sprintf("%*s&", length($_) - length($(\
gsub(" [^ /]*gres[/]gpu=|[,: ][^= ] =[^,: ] ", _)*_)),_))'
甚至更簡潔但更糟糕的語法樣式:
awk 'sub("[^ ]*$",sprintf("%*s&",length^gsub(" [^ /]*gres\/gpu=|"\
"[,: ][^= ] =[^,: ] ",_)^_ - length,_) )'
uj5u.com熱心網友回復:
這可能對您有用(GNU sed):
sed -E '/=/!b
s/\S /\n&\n/2;h
s/.*\n(.*)\n.*/\1/
/gpu=/!{s/./ /g;G;s/(^.*)\n(.*)\n.*\n/\2\1/p;d}
s/gpu=([^,]*)/\n\1 \n/;s/(.*)\n(.*\n)/\2\1/;H
s/.*\n//;s/./ /g;H;g
s/\n.*\n(.*)\n(.*)\n.*\n(.*)/\2\3\1/' file
本質上,上述解決方案涉及使用保持空間(參見此處并最終參見此處)作為暫存器來保存中間結果。這些結果是通過隔離第二個欄位然后再隔離 gpu 資訊來收集的。一步一步的故事如下:
如果該行不包含第二個欄位,請不要理會。
用換行符包圍第二個欄位并制作副本。
隔離第二個欄位
如果第二個欄位不包含 gpu 資訊,則用空格替換整個欄位并使用副本,相應地格式化該行。
否則,隔離 gpu 資訊,將其移動到行的前面,并將其附加到保留空間中的行副本。
同時,從模式空間中洗掉 gpu 資訊,并將模式空間中的每個字符替換為一個空格。
將這些空格附加到副本,然后由副本覆寫模式空間。
最后,知道行的每個部分都已被換行符分割,將這些部分重新組合成所需的格式。
NB 該解決方案取決于列的間距是實際空間。如果檔案中有制表符,則添加 sed 命令s/\t/ /g(在示例中,制表符被 8 個空格替換)。
選擇:
sed -E '/=/!b
s/\S /\n&\n/2;h
s/.*(\n.*)\n.*/\1/;s/(.)(.*gpu=)([^,] )/\3\1\2/;H
s/.*\n//;s/./ /g;G
s/(.*)\n(.*)\n.*\n(.*)\n(.*)\n.*$/\2\4\1\3/' file
在這個解決方案中,我沒有將具有第二個欄位但沒有 gpu 資訊的行作為一個單獨的案例來處理,而是為這個缺失的資訊引入了一個占位符,并遵循與存在 gpu 資訊相同的解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/490105.html
上一篇:LinuxGLFW-VulkanSurface未創建:glfwWindowHint(GLFW_CLIENT_API,GLFW_NO_API)被忽略?
