[英]How can I replace lines in a text file with lines from another file based on matching pattern?
[英]How can i reoder lines in a text file based on a pattern?
我有一個包含 4 行批次的文本文件,每個批次的第一行位於正確的位置,但接下來的 3 行並不總是按正確的順序排列。
name cat
label 4
total 5
value 4
name dog
total 4
label 3
value 6
name cow
value 6
total 1
label 4
name fish
total 3
label 5
value 6
我希望每個 4 行批次采用以下格式:
name cat
value 4
total 5
label 4
所以輸出將是:
name cat
value 4
total 5
label 4
name dog
value 6
total 4
label 3
name cow
value 6
total 1
label 4
name fish
value 6
total 3
label 5
該文件總共包含數千行,所以我想構建一個命令來處理這 3 行的所有潛在順序,如果格式不正確,則重新排列它們。
我知道我可以使用 awk 搜索以特定字符串開頭的行,然后重新排列它們:
awk '$1 == "value" { print $3, $4, $1, $2; next; } 1'
但是我不知道如何實現類似的處理多行的東西。
我怎樣才能做到這一點?
通過將RS
設置為空字符串,由至少一個空行分隔的每個文本塊被視為單個記錄。 從那里可以輕松捕獲每個鍵值對並按所需順序輸出它們。
BEGIN {RS=""}
{
for (i=1; i<=NF; i+=2) a[$i] = $(i+1)
print "name", a["name"] ORS \
"value", a["value"] ORS \
"total", a["total"] ORS \
"label", a["label"] ORS
}
$ awk -f a.awk file
name cat
value 4
total 5
label 4
name dog
value 6
total 4
label 3
name cow
value 6
total 1
label 4
name fish
value 6
total 3
label 5
你能不能試試以下。
awk '
/^name/{
if(name){
print name ORS array["value"] ORS array["total"] ORS array["label"] ORS
delete array
}
name=$0
next
}
{
array[$1]=$0
}
END{
print name ORS array["value"] ORS array["total"] ORS array["label"]
}
' Input_file
編輯:添加 Kvantour 先生建議的上述精煉解決方案。
awk -v OFS="\n" '
(!NF) && ("name" in a){
print a["name"],a["value"],a["total"],a["label"] ORS
delete a
next
}
{
a[$1]=$0
}
END{
print a["name"],a["value"],a["total"],a["label"]
}
' Input_file
最簡單的方法如下:
awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"}
{ for(i=1;i<=NF;++i) { k=substr($i,1,index($i," ")-1); a[k]=$i } }
{ print a["name"],a["value"],a["total"],a["label"] }' file
這是如何運作的?
awk 知道記錄和字段的概念。 文件被分割成記錄,其中連續的記錄被記錄分隔符RS
分割。 每條記錄都拆分為字段,其中連續的字段由字段分隔符FS
拆分。 默認情況下,記錄分隔符RS
設置為 <newline> 字符 ( \\n
),因此每條記錄都是一行。 記錄分隔符的定義如下:
RS
:的字符串值的第一個字符RS
應輸入記錄分隔符; 默認為 <newline>。 如果RS
包含多個字符,則結果未指定。 如果RS
為空,則記錄由由 <newline> 加上一個或多個空行組成的序列分隔,前導或尾隨空行不應在輸入的開頭或結尾導致空記錄,並且 <newline> 應無論FS
的值是什么,始終是字段分隔符。
因此,使用您提供的文件格式,我們可以根據RS=""
和字段分隔符 `FS="\\n" 定義記錄。
每條記錄看起來都簡化為:
key1 string1 << field $1
key2 string2 << field $2
key3 string3 << field $3
key4 string4 << field $4
...
keyNF stringNF << field $NF
當 awk 讀取一條記錄時,我們首先通過將所有key-value
對存儲在數組a
解析它。 之后,我們要求打印我們覺得有趣的值。 為此,我們需要定義輸出字段分隔符OFS
和輸出記錄分隔符ORS
。
在 Vim 中,您可以使用逆序排序對文件進行分段sort!
:
for i in range(1,line("$"))
/^name/+1,/^name/+3sort!
endfor
從 shell 發出的相同命令:
$ ex -s '+for i in range(1,line("$"))|/^name/+1,/^name/+3sort!|endfor' '+%p' '+q!' inputfile
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.