選擇文件的一部分

選擇文件的一部分

我有一個格式如下的文件:

title1
        line
        line

title2
        line
        line

        line

title3
        line
        line

我想提取下面的部分title2並刪除縮排。我目前正在使用sed(但是awkor shell 腳本適合我的上下文,遺憾的是不是像perlorpython這樣的語言):

sed -n -e '/^title2$/,/^[a-zA-Z]/ { /^[a-zA-Z]/ d ; s/^[ \t]*// ; p }'

但這會在末尾留下邏輯上的空白行(邏輯上是因為它可能有空格或製表符)。我想擺脫它。請注意,該部分中可能還有其他邏輯上的空白行需要保留(或/^[ \t]*$/ d可以完成工作)。因此我想要這個結果:

line
line

line

我可以額外進行一次sed -e '$d',但我想知道是否可以避免第二個過程。

答案1

我使用了保留空間,最後我得到了

sed -ne '/^title2$/,/^[a-zA-Z]/ { /^title2$/ { n; h; b; } ; /^[a-zA-Z]/ d; H; x; s/[ \t]*//; P; s/.*\n//; x }'

這似乎正確地處理了我關心的案件。

答案2

  • 如果它是“純”行(沒有製表符或白色),也將其刪除/^$/
  • 用於「邏輯」空白使用/^\s*$/

    sed -n -e '/^title2:/,/^[a-zA-Z]/ { /^[a-zA-Z]/ d ; /^$/ d ; s/^[ \t]*// ; p }' 
    

在哪裡

  • /^$/匹配起始行、結束行
  • /^\s*$/匹配起始行、零個或多個空格或製表符、行尾

答案3

sed -n '/title2/,/^\S/ { //b; /^\s*$/ { N; /\n\S/q; P; D }; s/^\s*//; p }'

我最初這樣做是為了引起@Archemar 的注意。如果可以的話我真的很感激回覆我在這篇文章中的評論只要你有時間。即使答案是「我不知道」。謝謝。

至少在我的 bash shell 中,它無需-e.只是好奇為什麼需要它?而如果\s或者\S不支持,您可以分別用[ \t]'s 和[^ \t]'s 替換它們。

對於像我第一次看到這個問題時一樣一無所知的人來說:

  • -n關閉自動列印
  • /title2/,/^\S/是搜尋範圍sed(從字串第一次出現的行「title2」到以非空格字元開頭的下一行[ie title3]包容性的
  • {只是意味著將隨附的命令應用於我剛剛指定的範圍或模式
    • //b允許以下命令不適用於範圍的開始和結束。
      更確切地說,如果您匹配title2^\S只是分支到腳本的末尾(b)(處理文件中的下一行,如果還有剩餘的話),因為在GNUsedBSD類似的說法,不確定是否還有其他版本sed

      '//' 重複最後一個正規表示式匹配

    • /^\s*$/符合範圍內的「邏輯空白」行。
    • {
      • N; /\n\S/q;因此,如果它是「邏輯空白」行,N則將下一行新增至模式空間,然後如果下一行是下一個標題,則它完全退出處理(q),因此「邏輯空白」行和下一個標題都不是列印。
      • P; D如果「邏輯空白」行不是接下來是下一個標題,然後只是列印“邏輯空白”行(P),然後只是從模式空間中刪除「邏輯空白」行,留下加入到模式空間的下一行,N從腳本的開頭開始處理( D)
    • }
    • s/^\s*//; p去掉行開頭的空格和製表符並列印格式化的行
  • }

@Archemar 請幫助

相關內容