2

我正在努力创建一个 sed 正则表达式命令来更改这样的行:

In file included from dira/file_a.h:8, dire/file_e.h:9, and dirf/file_f.h:10,
             from dirb/file_b.h:6,
             from /existing/abs/path/dirb/file_b.cc:6:
dirc/file_c.h:88: error: 'eqn_count_t' does not name a type
dirc/file_c.h:95: error: 'wave_count_t' does not name a type
dirc/file_c.h:104: error: ISO C++ forbids declaration of 'WmHyperbolicEqnSet' with no type

到这个期望的输出

In file included from /abspaths/dira/file_a.h:8, /abspaths/dire/file_e.h:9, and /abspaths/dirf/file_f.h:10,
             from /abspaths/dirb/file_b.h:6,
             from /existing/abs/path/dirb/file_b.cc:6:
/abspaths/dirc/file_c.h:88: error: 'eqn_count_t' does not name a type
/abspaths/dirc/file_c.h:95: error: 'wave_count_t' does not name a type
/abspaths/dirc/file_c.h:104: error: ISO C++ forbids declaration of 'WmHyperbolicEqnSet' with no type

所以,

  • 仅匹配以 .h 结尾的相对路径+文件名
  • 不匹配以正斜杠开头的行(因此已经是绝对路径)
  • 匹配每行多次出现
  • 很明显,我需要一个与Mac OS X的 BSD sed 命令配合使用的命令。

我想要的 regex 和 sed 命令是什么?

我正在尝试修改 gcc 输出,因为包含的带有错误/警告的头文件会生成错误流输出,其中引用了相对路径,而不是绝对路径。使用我的 XCode IDE 调用外部构建系统,.h 文件中发生的错误不是“可点击的”。

4

3 回答 3

3

上次编辑

我终于成功地创建了这样一个命令,只有 1 个命令:

sed 's/^\(.* \)\{0,1\}\([^/ ][^ ]\{1,99\}\.h\)/\1\/abspath\/\2/;' testfile.txt

并且为了支持多重匹配......即使在 Mac 上也是如此(来自@sudo_O 的一些简化想法):

sed -E -e :a -e 's/^(.* )?([^/][^ ]+\.h)/\1\/abspath\/\2/' -e ta testfile.txt 

但是 Mac 的sed不支持;作为命令分隔符的实现。所以我们需要使用多个-e命令字段。

为了测试它们,我textfile.txt使用以下命令进行了修改:

sed -e '4s/^.*$/& &/' -i.bak testfile.txt

(也可以在 Mac 上工作)

有两个部分,首先可以计算任何字符串,但以空格结尾...... 0 或 1 次。第二部分不能以空格或斜杠开头,可以包含任何内容,但不能包含空格,并且必须以 . 结尾.h。如果匹配,第一部分(包含前导空格,但如果为 0 次则可能为空)必须跟在, 后面/abspath/,而不是第二部分。

年长者

这不工作吗?

为 Mac 修改的编辑:

sed 's/ \([^/ ][^ ]\{1,99\}\.h\)/ \/abspath\/\1/;' testfile.txt

在 mac 和 Linux 上工作相同。我已经替换+{1,99}.

对不起,我没有正确阅读这个问题。这对两者都有效:

sed 's/^\([^/ ][^ ]\{1,99\}\.h\)/\/abspath\/\1/;
     s/ \([^/ ][^ ]\{1,99\}\.h\)/ \/abspath\/\1/;' testfile.txt
于 2012-12-30T23:09:57.780 回答
2

Mac 和 Linux 友好:

sed -E 's/^([^/][a-zA-Z/_]+\.h)/\/abspaths\/\1/;s/ ([^/][a-zA-Z/_]+\.h)/ \/abspaths\/\1/g' file

匹配所需的输出:

In file included from /abspaths/dira/file_a.h:8, /abspaths/dire/file_e.h:9, and /abspaths/dirf/file_f.h:10,
             from /abspaths/dirb/file_b.h:6,
             from /existing/abs/path/dirb/file_b.cc:6:
/abspaths/dirc/file_c.h:88: error: 'eqn_count_t' does not name a type
/abspaths/dirc/file_c.h:95: error: 'wave_count_t' does not name a type
/abspaths/dirc/file_c.h:104: error: ISO C++ forbids declaration of 'WmHyperbolicEqnSet' with no type

解释:

当替换不在行首时,需要两次替换来说明所需的额外空间:

s/^([^/][a-zA-Z/_]+\.h)/\/abspaths\/\1/;   # First substitution for start of line 
s/ ([^/][a-zA-Z/_]+\.h)/ \/abspaths\/\1/g  # Second for non-start of line

# Match (first substitution)
s/
^             - start of line
(             - capture group 
[^/]          - not a forward slash 
[a-zA-Z/_]+   - one or more letter, forward slash or underscore
\.h           - the extension (escaped) 
)             - end capture group 
# Replace with 
/
\/abspaths\/  - the literal string /abspaths (slashes escaped)
\1            - the captured group 
/;
# Match (second substitution)
s/
' '           - not start of line but a single space (used quotes here for space)
(             - capture group 
[^/]          - not a forward slash 
[a-zA-Z/_]+   - one or more letter, forward slash or underscore
\.h           - the extension (escaped) 
)             - end capture group 
# Replace with 
/
' '           - put the single space back
\/abspaths\/  - the literal string /abspaths (slashes escaped)
\1            - the captured group 
/g            - global flag

或者仅通过进行一次替换(基于F.Hauri)答案,但每行仅适用于一场比赛:

sed -E 's/^(.* )?([^/][^ ]+\.h)/\1\/abspath\/\2/' file

对于多个匹配sed支持分支

sed -E ':a;s/^(.* )?([^/][^ ]+\.h)/\1\/abspath\/\2/;ta' file
于 2012-12-30T22:44:47.483 回答
0

试试这个:

sed "s|\([^\s]*\.h\)|/abspath/\1|" <testfile.txt

并忽略绝对路径:

sed "s|^\([^/][^\s]*\.h\)|/abspath/\1|" <testfile.txt
于 2012-12-30T22:28:34.230 回答