簡體   English   中英

如何根據模式重新編碼文本文件中的行?

[英]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.

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