选择文件的一部分

选择文件的一部分

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

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 请帮助

相关内容