【问题标题】:How do i select multiple lines between markers (*) excluding the last one (using sed)? And how do I select all the rest?如何在标记(*)之间选择多行,不包括最后一行(使用 sed)?以及如何选择所有其余部分?
【发布时间】:2016-07-04 11:03:51
【问题描述】:

我有一个巨大的 .txt 文件,格式如下(每个非空行都以三个空格开头):

   unwanted text
   unwanted text

   *wanted text
   abc
   def

   *wanted text 2
   content
   content

   *wanted text 3
   content
   content

   (...)

我正在寻找一个代码,它只返回从第一个“*”出现到(但不包括)第二个“*”出现的行。

浏览多个 StackOverflow 帖子后,我设法使用 Ubuntu (GNU/Linux) 获得了以下工作代码:

sed -n -e '/^   \*/{p;q}' bigfile.txt && sed -e '1,/   \*/d' -e '/   \*/,$d' bigfile.txt

它给了我以下(根据需要)输出:

*wanted text
abc
def
\n (representing a wanted blank line)

虽然这正是我想要的输出,但你必须同意我的观点,这是一个有点愚蠢的代码,因为我必须使用 sed 两次。首先,我只有它的第二部分(在“&&”之后)并且会返回正确的东西,除了第一行(*想要的文本)。然后我附加了代码的第一部分(在“&&”之前),所以我也得到了想要的部分的第一行。我尝试过的所有其他代码都没有得到更好的结果。

光说是不够的,这是一个非常大的文件,我将在脚本中递归地执行此操作,因此,如果可能,最好使用 /q(找到第一个结果后退出)。

完成此操作后,我需要将最后一个命令的结果作为输入的东西,这样我就可以得到除了先前​​结果之外的整个文本,如下所示:

   unwanted text
   unwanted text

   *wanted text 2
   content
   content

   *wanted text 3
   content
   content

   (...)

所以,总而言之,我的 2 个问题是:

  • 有没有一种方法可以使用 sed 单线获得如上所述的第一个所需输出,而无需调用 sed 两次(最好在找到摘录后退出,这样它就不会搜索所有大文件)?我很确定有一个更优雅的解决方案。
  • 我怎样才能得到“除前一个问题的结果之外的整个文本”的输出(如“反向”输出?)? 我没有软件要求,我只需要它,这样我就可以运行之前的 一次又一次地采取行动并“不断更新”输入并处理每个 根据具体情况输出第一条命令。

希望我足够清楚。请问我是否缺少任何细节。 非常感谢您的关注!

【问题讨论】:

标签: regex linux bash sed


【解决方案1】:

awk 来救援!

$ awk '$1~/^*/{if(f) exit; f=1} f' file

   *wanted text
   abc
   def
   <-- here is the empty line formatter eats

第二部分

$ awk '$1~/^*/{f++} !f||f>1' file

   unwanted text
   unwanted text

   *wanted text 2
   content
   content

   *wanted text 3
   content
   content

   (...)

【讨论】:

  • 通常您可以使用&lt;pre&gt;&lt;code&gt;...&lt;/code&gt;&lt;/pre&gt; 修复格式但无法正常工作。
  • 嘿,这很完美!非常感谢!这是一个非常优雅的解决方案。我注意到“反斜杠”字符不会出现在我的计算机上,因此它不会显示您必须写“反斜杠”“”而不是简单的“”,因为 sed 会识别星号作为特殊字符。
猜你喜欢
  • 2020-03-05
  • 1970-01-01
  • 2018-01-05
  • 1970-01-01
  • 2020-01-30
  • 1970-01-01
  • 2017-02-12
  • 2016-06-15
  • 1970-01-01
相关资源
最近更新 更多