如何抓取换行符后的文本

如何抓取换行符后的文本
假设:

这是我显示的唯一文字。剩下的文本有更多数据[未显示],这是问题所在。文本是半干净的,充满空格、制表符、Unicode,不干净,必须像这样[我的需要],所以复制/粘贴这个确切的文本不起作用[由标记格式化]:

我有一些像这样的文字:

*** *
more text with spaces and  tabs                                                             
*****
1
Something here and else, 2000 edf, 60 pop
    Usd324.32           2 Usd534.22
2
21st New tetx that will like to select with pattern, 334 pop
    Usd162.14

*** *
more text with spaces and tabs, unicode
*****

我试图抓住这个明确的文本:

  • 1 Something here and else, 2000 edf, 60 pop Usd324.32

由于newlineand whitespace,下一个命令仅抓取1

grep -E '1\s.+'

另外,我一直在尝试用新的连接来实现:

grep -E '1\s|[A-Z].+' 

但不起作用,grep开始在文本的不同部分选择相似的模式

awk '{$1=$1}1'   #done already
tr -s "\t\r\n\v" #done already
tr -d "\t\b\r"   #done already

我怎样才能抓住:

  • 抢1newline
  • 之后抓住整个第二行1 newline
  • 抓住号码$Usd324.34并删除Usd

答案1

pcregrep具有ultiline 模式和输出捕获组内容的M能力:o

$ pcregrep -Mo1 -o2 -o3 --om-separator ' ' '^(1)\n(.*)\n\h*Usd(\H+)' file
1 Something here and else, 2000 edf, 60 pop 324.32

答案2

  • 要连接并修改从仅包含“1”和可选空格的行开始的三行:
$ perl -0777ne '/^1\s+(.*?)\h*\n\h*Usd(\H+)/imsg && printf "1 %s %s\n", $1, $2' input.txt
1 Something here and else, 2000 edf, 60 pop 324.32

-0777选项告诉 perl 一次读入整个文件,而不是一次读一行。 -n告诉它以类似的方式处理输入sed -n-e告诉 perl 下一个参数是一个脚本。

如果正则表达式与文本匹配,它将以所需的格式打印 RE 捕获组捕获的文本。

匹配“可选尾随空格”是为了处理这样一个事实:我从您的问题复制粘贴的示例文件在多行上有尾随空格字符。我不知道这是否在您的原始文件中,或者是否只是您将其粘贴到问题中的产物 - 没关系,无论尾随空格是否存在,脚本都会以相同的方式工作。

  • 要加入和修改以仅包含数字和可选空格的行开头的三行的任何分组:
$ perl -n -e 'if (/^\d+\s*$/) {
     chomp; $_ .= " " . <>;
     chomp; $_ .= " " . <>;
     s/\s{2,}/ /g;
     s/Usd(\H+).*/$1/i;
     print
   }' input.txt
1 Something here and else, 2000 edf, 60 pop 324.32
2 21st New tetx that will like to select with pattern, 334 pop 162.14

每当一行仅包含带有可选尾随空格的数字时,它会获取接下来的两行,将它们附加到当前行,然后修改并打印它。

去除chomp每行末尾的换行符,并<>读取下一行输入。它执行两次以获取并附加以下两行。然后,它通过两个操作修改连接行s///(第一个操作将两个或多个空白字符减少为单个空格,第二个操作删除第一个“Usd\H+”之后的行中的所有内容,同时还删除文字字符串“Usd”。最后的操作在打印之前完成(不区分大小写)。

\h是 Perl 正则表达式,用于匹配任何水平空白字符。 \H是相反的,匹配任何不是水平空白。

  • 这两个 perl 单行代码都可以与您的原始示例数据和编辑问题中的更新示例一起工作(并产生相同的输出)。

答案3

你可以awk这样使用:

$ awk 'BEGIN {count = 0; ORS=" "} /^1$/ {found = 1; print; next; count++} found && count < 1 {count++; print; next} count == 1 {print $1; exit} END {printf "\n"}' < FILE
1 Something here and else, 2000 edf, 60 pop 324.32

或者使用getline()

awk 'BEGIN {ORS=" "} /^1$/ {getline; print; getline; print $1} END {printf "\n"}' < FILE

答案4

sed也适合这项工作:

sed -n '/^1 $/{h;n;H;n;s/^ *\([0-9.]*\).*/ \1/;H;g;s/\n//g;p}' sample

相关内容