使用linux有选择地从文本文件中解析注释和值

时间:2012-08-01 00:48:36

标签: linux parsing shell

我想在一些名称块的顶部解析一个带有名称和注释的文件。如果我有一个像:

这样的文件
Art
Boat
Road
Tree
Street

# Blah
Star
Car
Sun

Sock

# Comm1
# Comm2
Stop
Stick
# Comm
Stock
Dock

我希望以某种方式解析此文件,以便提取以“S”开头的所有名称及其相应的注释。相应的注释是紧接在前的注释块(一行或多行注释),直到在它之前遇到空白空间。此外,一个注释块适用于其后的所有条目,直到遇到空格或其他注释块。所以上面输入的输出应该是这样的:

**Name      Comments**

Street
Star        # Blah
Sun         # Blah
Sock
Stop        # Comm1 # Comm2
Stick       # Comm1 # Comm2
Stock       # Comm

任何人都可以建议一个好方法去做(最好使用shell)吗?真的很感激。谢谢!

PS:如果我在描述中不清楚,我会道歉,但仍然是新的。

2 个答案:

答案 0 :(得分:1)

这是一个稍微不那么优雅的工作:

awk '/^$/ {ca=""; cp=""} /^#/ {ca=ca " " $0} /^S/ && ca {cp=ca; ca=""} /^S/ {print $0 " " cp}' < input.txt > output.txt

有两个商店:评论累加器ca和评论打印缓冲区cp

  1. 每当遇到空行时,两者都会被清除。
  2. 遇到评论行时,会将其添加到评论累加器。
  3. 当遇到以S开头的行且注释累加器有内容时,注释打印缓冲区被设置为注释累加器中的任何内容,后者被清除。
  4. 当遇到以S开头的行时,会打印出来后跟注释打印缓冲区中的任何内容。
  5. 这可能是一种更优雅的方式来做到这一点,这无疑有问题(例如,在行的末尾放置空格而没有注释),但它会让你开始。

答案 1 :(得分:1)

假设您的空行不包含空格:

sed -n '/^#/H; /^S/{G; y/\n/ /; p}; /^$/h' input

第一个命令(/^#/H)将当前行(注释)附加到保留空间。 下一个命令将保留空间(包含所有累积的注释)附加到当前缓冲区,用一个空格替换所有换行符,然后打印该行。只要遇到空行,最后一个命令就会清除保留空间。

编辑(感谢blahdiblah)

如果在没有前一个空白行的情况下检测到新的注释块,则上述操作不会正确重置累加器。这很丑陋,但解释了这个:

sed -n '/^#/{h; bk}; :j /^S/{G; y/\n/ /; p}; /^$/h; d; :k n; /^#/{ H; bk}; bj;' input