簡體   English   中英

使用 sed 重命名文本文件中的特定行

[英]rename specific lines in a text file with sed

我有一個看起來像這樣的文件:

>alks|keep1|aoiuor|lskdjf
ldkfj
alksj
asdflkj
>jhoj_kl|keep2|kjghoij|adfjl
aldskj
alskj
alsdkj

我想只編輯以>開頭的行,最好是就地編輯,以獲取文件:

>keep1
ldkfj
alksj
asdflkj
>keep2
aldskj
alskj
alsdkj

我知道原則上這可以通過 sed/awk/cut 的各種組合來實現,但我一直無法找出正確的組合。 理想情況下它應該很快——文件有數百萬行,而且許多行也很長。

關於我要編輯的行的關鍵內容:

  • 始終以>開頭
  • 我想保留的位總是在第一個和第二個 pipe 符號之間| (因此思考cut會有所幫助
  • 我想保留的位有字母數字符號,有時還有下划線。 同一行字符串的 rest 可以有任何符號

我嘗試過的似乎很有幫助

(我的大多數 sed 嘗試都是純垃圾)

cut -d '|' -f 2  test.txt

得到我想要的字符串,它也保留其他行。 所以它很接近,但是(當然)它不會在cut應用的行上保留初始> ,因此它缺少解決方案的關鍵部分。

使用sed

sed -E '/^>/ s/^[^|]+\|([^|]+).*/>\1/'
  • /^>/到 select 以>開頭的行,對於給定的樣本不是絕對必要的,但有時這比單獨使用s提供更快的結果
  • ^[^|]+\| 這將匹配非| 從行首開始的字符
  • ([^|]+)捕獲第二個字段
  • .* rest 的線
  • >\1替換字符串,其中\1將具有([^|]+)的內容

如果您的輸入只有 ASCII 字符,這將為您提供更快的結果:

LC_ALL=C sed -E '/^>/ s/^[^|]+\|([^|]+).*/>\1/'

定時

  • 通過從給定的輸入樣本創建一個大文件來檢查時序結果, awk更快,而mawk甚至更快
  • 但是,OP報告說sed解決方案對於實際數據更快

使用您顯示的示例,您可以簡單地嘗試以下操作。 在此代碼中,我們將字段分隔符設置為| 對於 Input_file 的所有行,然后在主程序中檢查行是否從>開始,然后打印第二個字段,否則打印完整的行。

awk -F'|' '/^>/{print ">"$2;next} 1' Input_file

說明:為上述添加詳細說明。

awk -F'|' '     ##Starting awk program from here and setting field separator as | here.
/^>/{           ##Checking condition if line starts from > then do following.
  print ">"$2   ##Printing 2nd field of current line here.
  next          ##next will skip all further statements from here.
}
1               ##Will print current line.
' Input_file    ##mentioning Input_file name here.

您還可以使用以下awk命令:

awk  -F\| '/^>/{print ">"$2} !/^>/{print}' file
# Inplace replacement with gawk (GNU awk)
gawk -i inplace  -F\| '/^>/{print ">"$2} !/^>/{print}' file
# "Inline-like" replacement with any awk
awk -F\| '/^>/{print ">"$2} !/^>/{print}' file > tmp && mv tmp file

這里,

  • -F\| - 將字段分隔符設置為| 字符
  • /^>/是條件:如果行以<開頭(而!/^>/表示相反)
  • {print ">"$2}打印字段 2 的值,並在其前面加上>字符
  • {print}只是打印整行。

請注意,由於!/^>/{print}可以簡化為!/^>/因為print是默認操作。

查看在線演示

s='>alks|keep1|aoiuor|lskdjf
ldkfj
alksj
asdflkj
>jhoj_kl|keep2|kjghoij|adfjl
aldskj
alskj
alsdkj'
awk  -F\| '/^>/{print ">"$2} !/^>/{print}' <<< "$s"

Output:

>keep1
ldkfj
alksj
asdflkj
>keep2
aldskj
alskj
alsdkj

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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