regex和sed命令匹配相对路径文件名

时间:2012-12-30 22:22:03

标签: regex bash sed osx-mountain-lion

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

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命令的命令。

我想要的是什么是正则表达式和sed命令?

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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支持branching

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

答案 2 :(得分:0)

试试这个:

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

忽略绝对路径:

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