在bash中操作多行部分

时间:2013-10-15 18:47:35

标签: regex bash sed grep

我希望从文本文件中提取并预先添加到一个部分中的项目列表。 Sed和grep几乎可以工作,但是他们需要大量的黑客攻击。是否有另一个实用程序可以使这更容易,也许是awk?

首先,提取。我想要一个“section [”和“]”之间的所有项目的列表,但是在第一个模式中可能有空格/换行符,这使得后视图变得困难。新行是一个很好的列表分隔符,所以我只想要特定部分的“[”和“]”之间的所有字符(即'section []'而不是'wrongSection []')

文本示例(每个文件只有1个部分):

文件1:

section []
wrongSection [foo]

输出1空

文件2:

section [item1]
wrongSection [foo]

输出2:

item1

文件3:

section
[
    item1
    item2
]
wrongSection [foo]

输出3:

item1
item2

Grep可用于抓取它,但它不会忽略非捕获组

$ grep -Po "(?ims)^(?:\s*section\s*\n*\s*\[).*?(?:\])" file.txt

我的第二个问题是增加一个新项目('itemX')。 Sed讨厌多线,但如果我假设[在1行内

,则以下工作
$ sed '/^\s*section/N;/^\s*section\s*\n?\s*\[/a itemX' file.txt

总之,我试图在输出中不想要的可能多线模式之间读取/前置多行。我最好不要使用perl / groovy / python /等来删除bash吗?

2 个答案:

答案 0 :(得分:1)

使用非gnu awk:

awk -v FS='[ \n]*[\\[\\]][ \n]*' '{gsub(/\n+ +/, "\n");
           for(i=1; i<=NF; i+=2) {if ($i=="section") print $(i+1)}}' RS= file

\n
item1\n
item1\n
item2\n

答案 1 :(得分:1)

试试这个,它适用于任何现代的awk:

$ cat file1
section []
wrongSection [foo]
$ 
$ awk -v RS=']' 'sub(/.*section[[:space:]]+\[*/,""){gsub(/^\n+|\n+$/,""); gsub(/[[:blank:]]/,""); print; exit}' file1


$ cat file2                                                                   
section [item1]
wrongSection [foo]
$ 
$ awk -v RS=']' 'sub(/.*section[[:space:]]+\[*/,""){gsub(/^\n+|\n+$/,""); gsub(/[[:blank:]]/,""); print; exit}' file2
item1

$ cat file3                                                                   
section
[
    item1
    item2
]
wrongSection [foo]
$ 
$ awk -v RS=']' 'sub(/.*section[[:space:]]+\[*/,""){gsub(/^\n+|\n+$/,""); gsub(/[[:blank:]]/,""); print; exit}' file3
item1
item2
$