sed脚本中的循环不会终止

时间:2016-11-20 20:19:31

标签: regex sed

说我有这样的文件:

...
{
     ...
     cout<< "---at time:\t\t"<< sc_core::sc_time_stamp()<<"\n\n" << endl;
     ...
     cout<< "---at time:\t\t"<< sc_core::sc_time_stamp()<<"\n\n" << endl;
     ...
}
...
{
     ...
     if(strcmp(argv[1], "--io_freq1_Mhz") != 0)
     if(strcmp(argv[2], "--io_freq2_Mhz") != 0)
     ...
     if(strcmp(argv[11], "--bytes_per_word") != 0)
     ...
     if(strcmp(argv[23], "--mem_size_bytes") != 0)
     ...
}

我首先要做的是,使用sed,加载包含模式的所有行     “--foo” 进入模式空间并打印出paranthesis中的部分,所以我使用命令:

sed -n -e 's/.*[^-]\(-\{2\}[^-].*\)"\(.*\)/\1/p' file

这正是我想要的,所以我得到了输出:

--io_freq1_Mhz
--io_freq2_Mhz
...
--bytes_per_word
...
--mem_size_bytes

接下来我想将所有行合并为一个并用空格分隔内容。我可以使用命令替换来解决这个问题:

echo `sed -n -e 's/.*[^-]\(-\{2\}[^-].*\)"\(.*\)/\1/p' file`

这给了我:

--io_freq1_Mhz --io_freq2_Mhz --... --bytes_per_word --... --mem_size_bytes

接下来我想在参数之间插入一个数字,例如1,所以最终的结果应该是这样的:

--io_freq1_Mhz 1 --io_freq2_Mhz 1 --... 1 --bytes_per_word 1 --... 1 --mem_size_bytes 1

我几乎可以解决这个问题。我正在使用命令:

echo `sed -n -e 's/.*[^-]\(-\{2\}[^-].*\)"\(.*\)/\1/p' file` | sed -n -e ':start { s/\(--[^\ ]*\) -/\1 1 -/p; b start }' | sed -n -e 's/\(--.*[^\ ]\)/\1 1/p'

但我遇到两个小问题。首先,在我跳回到开始标记之前,输出被管道传输到最后一个sed语句,这意味着我得到了输出:

--io_freq1_Mhz 1 --io_freq2_Mhz --... --bytes_per_word --... --mem_size_bytes 1
--io_freq1_Mhz 1 --io_freq2_Mhz 1 --... --bytes_per_word --... --mem_size_bytes 1

等等。所以我的第一个问题是,我怎样才能避免每次输出到最后一个sed语句中。我可以使用不同的sed选项/标志来实现这一点吗?

第二个问题是该命令没有终止。迭代以

结束
--io_freq1_Mhz 1 --io_freq2_Mhz 1 --... --bytes_per_word 1 --... --third_last_item 1 --second_last_item mem_size_bytes 1

可以看出,在第二个最后一项后面没有附加'1',另外整个命令也没有终止。我必须使用Ctrl-C终止它。

1 个答案:

答案 0 :(得分:1)

使用第一个命令的微小修改:

sed -n -e 's/.*[^-]\(-\{2\}[^-].*\)"\(.*\)/\1 1/p' file | tr '\n' ' '

提取名称后,在其后面附加数字。 tr命令将换行符转换为空格。你可以在sed中完成所有工作;这将是繁琐的,这就是全部。

实际上,它并不是那么繁琐,但它需要一种不同的方式来看待这个过程。具体来说,您需要在保留空间中保存匹配模式,然后在输入结束时处理它们:

sed -n \
    -e '/.*[^-]\(-\{2\}[^-].*\)"\(.*\)/{ s//\1 1/; H; }' \
    -e '$ { x; s/\n/ /g; p; }' file 

BSD(macOS)}需要sed个字符前面的分号,而GNU sed则不行。第一个-e选项查找与您的模式匹配的行,然后对该行应用替换命令以仅保留--name部分加上数字1,然后将该信息附加到保留空间之后新队。第二个-e选项适用于最后一行。它交换模式并保存空格,然后用空格替换每个换行符并打印结果,包括带有tr的脚本替换为空白的尾随换行符。

输出(注意前导空格):

 --io_freq1_Mhz 1 --io_freq2_Mhz 1 --bytes_per_word 1 --mem_size_bytes 1

如果您不想要前导空格,请在打印前将其删除(在s/^ //;之前添加p)。