多行匹配后用sed打印行

时间:2013-06-07 01:34:26

标签: regex sed multiline

我正在尝试创建一个脚本来从文件中提取帐户代码。文件本身很长并且包含很多其他数据,但我在下面列出了我正在查看的部分的摘录(此摘录之前和之后还有其他内容)

我感兴趣的文件部分有时看起来像这样

  Account       Customer Order No.          Whse         Payment Terms          Stock No.          Original Invoice No.
                                                                                                       VIN No.
 AAAAAA01             9999                  1000             30 days

有时看起来像这样

  Account       Customer Order No.          Whse         Payment Terms          Stock No.          Original Invoice No.
 AAAAAA01             9999                  1000             30 days

(一个字段切断了末端,那个字段已经包裹在它自己的行上)

我知道我可以使用| tr -s ' ' | cut -d ' ' -F 1来提取代码,但是这不是设置的行号(此部分之前的内容是动态的)。

我首先尝试使用额外字段来处理这个案例,我认为这很容易与?

进行可选匹配

用于分隔字段的空格数可以更改,因为它基本上是OCRed。

到目前为止我的一些尝试 - (假设文件来自STDIN)

| sed -n '/\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.\s\+VIN No\.\s*/{n;p;}'
| sed -n '/\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.\s*\n\s*VIN No\.\s*/{n;p;}'
| sed -n '/\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.\s*\r\s*VIN No\.\s*/{n;p;}'
| sed -n '/\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.\s*\r\n\s*VIN No\.\s*/{n;p;}'

这些都无法匹配

| sed -n '/\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.\s*/,/\s\*VIN No\.\s*/{n;p;}'

这至少匹配了一些东西,但令人沮丧地打印了VIN编号行,然后是每隔一行。似乎将标记作为表达式的可选部分会更加困难。

所以,给定完整文件的输入(包括上述任一摘录),我正在寻找输出

AAAAAA01             9999                  1000             30 days

(我可以将其修剪为所需的数据)或AAAAAA01如果有更简单的方法可以直接进行此操作。

2 个答案:

答案 0 :(得分:3)

这可能适合你(GNU sed):

sed -n '/Account/{n;/VIN No\./n;p}' file

sed-n开关一起使用,这使得sed的行为类似grep,即仅使用命令P或(本例){{1}显式打印行}。

  • p匹配带有/Account/
  • 模式的行
  • 仅限上述比赛:
  • Account通常会打印当前行,然后将下一行读入模式空间,但是当n处于运行状态时,不会进行打印。所以现在模式空间包含下一行。
  • -n如果当前行包含/VIN No\./n,则有效清空模式空间并在下一行中读取。
  • Vin No打印当前在模式空间中的任何内容。

所以这是条件中的条件。当我们遇到p时,会打印以下行或其后的行。

答案 1 :(得分:1)

awk '/^\s*Account\s\+Customer Order No\.\s\+Whse\s\+Payment Terms\s\+Stock No\.\s\+Original Invoice No\.$/ { 
    getline;
    if (/^\s*VIN No\.$/) getline;
    print;
    exit;
}'