![sed 命令在带有参数的脚本中失败](https://linux22.com/image/197049/sed%20%E5%91%BD%E4%BB%A4%E5%9C%A8%E5%B8%A6%E6%9C%89%E5%8F%82%E6%95%B0%E7%9A%84%E8%84%9A%E6%9C%AC%E4%B8%AD%E5%A4%B1%E8%B4%A5.png)
我正在尝试执行两步字符串编辑:
- 匹配字符串“payload”。如果找到,则添加一些“#if #endif”代码,如输出文件中所示。
- 然后复制包含“payload”的行,将其替换为“upper_payload”,然后将其粘贴到“if endif”条件中。
输入文件:
Let's see if this works or not payload.
alskdjaslkdjn.
aslkdjbnalkgfjbaglbjbjdgfsbkgjbsg;
Also here is another_payload.
alskdjbnalgkjb.
kjhsdfjlkgfjlknbsgdfljkbgsbljk((*&)(&;
预期输出文件:
Let's see if this works or not payload.
#if defined(NV_C2C_UPPER_PD)
Let's see if this works or not upper_payload.
#endif
alskdjaslkdjn.
aslkdjbnalkgfjbaglbjbjdgfsbkgjbsg;
Also here is another_payload.
#if defined(NV_C2C_UPPER_PD)
Also here is another_upper_payload.
#endif
alskdjbnalgkjb.
kjhsdfjlkgfjlknbsgdfljkbgsbljk((*&)(&;
我最终在 shell 文件中提出了以下代码,以便我可以在多个文本文件上运行它:
#!/bin/csh -f
sed -i '/payload/a #if defined(NV_C2C_UPPER_PD)\n#endif' $1
sed -i "/NV_C2C_UPPER_PD/a `sed -n '/payload/s/payload/upper_payload/p' $1`" $1
使用上面的 shell 脚本,当我传递如下命令时:
> ./my_shell.sh test.txt
文本文件被修改为以下输出:
Let's see if this works or not payload.
#if defined(NV_C2C_UPPER_PD)
Let's see if this works or not upper_payload.
#endif
alskdjaslkdjn.
aslkdjbnalkgfjbaglbjbjdgfsbkgjbsg;
Also here is another_payload.
#if defined(NV_C2C_UPPER_PD)
Let's see if this works or not upper_payload.
#endif
alskdjbnalgkjb.
kjhsdfjlkgfjlknbsgdfljkbgsbljk((*&)(&;
它还在终端上给出此错误/警告:
sed: can't read Also here is another_upper_payload.: No such file or directory
在输出中,我们可以观察到第二个“upper_payload”替换不正确,因为行复制不正确。它复制了第一行,而不是包含“another_payload”的新行。
我尝试了不同的选择,但未能解决这个问题。希望得到一些帮助。
答案1
不要尝试调用另一个sed
进程来为其中一个sed
表达式创建输入,而是考虑s///
在找到触发子字符串 ( ) 后立即使用命令重新组织当前行payload
。
/payload/!b
s/.*/&\
#if defined(NV_C2C_UPPER_PD)\
&\
#endif/
s/payload/upper_&/2
上面的sed
编辑脚本首先跳过包含触发字符串的任何行。当不带标签使用时,(“branch”)命令b
会跳到脚本的最后。
在剩余的行上,我们将整个内容替换为自身,然后是该#if
行,再次替换原始行,然后是该#endif
行。s///
如果换行符如上所示进行转义,则可以使用该命令插入换行符(GNU 也sed
允许使用 插入文字换行符\n
)。
然后,该字符串的第二次出现将在单独的替换中payload
添加到该字符串的前面。upper_
此解决方案假设触发字符串不会在一行中多次出现,或者最后一次替换不会替换正确的子字符串。
在命令行上,
sed -e '/payload/!b' \
-e 's/.*/&\
#if defined(NV_C2C_UPPER_PD)\
&\
#endif/' \
-e 's/payload/upper_&/2' file
或者,为脚本使用单独的脚本文件,
sed -f script file
或者,使用脚本的此处文档,
sed -f /dev/stdin file <<'SED_SCRIPT'
/payload/!b
s/.*/&\
#if defined(NV_C2C_UPPER_PD)\
&\
#endif/
s/payload/upper_&/2
SED_SCRIPT
或者,使用 GNU sed
,
sed -e '/payload/!b' \
-e 's/.*/&\n#if defined(NV_C2C_UPPER_PD)\n&\n#endif/' \
-e 's/payload/upper_&/2' file
结果:
Let's see if this works or not payload.
#if defined(NV_C2C_UPPER_PD)
Let's see if this works or not upper_payload.
#endif
alskdjaslkdjn.
aslkdjbnalkgfjbaglbjbjdgfsbkgjbsg;
Also here is another_payload.
#if defined(NV_C2C_UPPER_PD)
Also here is another_upper_payload.
#endif
alskdjbnalgkjb.
kjhsdfjlkgfjlknbsgdfljkbgsbljk((*&)(&;
答案2
你可以试试这个sed
$ sed -i 's/\(.*\)\(payload\)\(.*\)/&\n#if defined(NV_C2C_UPPER_PD)\n\1upper_\2\3\n#endif/ ' input_file
\(.*\)\(payload\)
在这里,匹配被分为 2 组,这样我们就可以在返回时轻松地反向引用它们
&
将返回未更改的完整匹配项
\1upper_\2
这是我们按照要求的顺序返回分组的地方,第一个组一直匹配到payload
允许upper_
在之前插入payload
输出
$ sed 's/\(.*\)\(payload\)\(.*\)/&\n#if defined(NV_C2C_UPPER_PD)\n\1upper_\2\3\n#endif/' input_file
Let's see if this works or not payload
#if defined(NV_C2C_UPPER_PD)
Let's see if this works or not upper_payload
#endif.
alskdjaslkdjn.
aslkdjbnalkgfjbaglbjbjdgfsbkgjbsg;
Also here is another_payload
#if defined(NV_C2C_UPPER_PD)
Also here is another_upper_payload
#endif.
alskdjbnalgkjb.
kjhsdfjlkgfjlknbsgdfljkbgsbljk((*&)(&;
答案3
这里已经有很好的sed
解决方案,但我个人更喜欢awk
这个:
awk \
-v if='#if defined(NV_C2C_UPPER_PD)' \
-v endif='#endif' \
'
/payload/{
line=$0
gsub("payload","upper_payload",$0);
printf "%s\n%s\n%s\n%s\n",$line,if,$0,endif
next
}
1' file
答案4
仅使用 POSIXly 构造的一种方法:
sed -e 'p
/payload/!d
s//upper_&/
i\
#if defined(NV_C2C_UPPER_PD)
a\
#endif
' file
如果您不希望转义换行符,您可以执行以下操作,同时仍然符合 POSIXly:
sed -e 'p
/payload/!d
s//upper_&/
H;s/.*//;x;G
s/^/#if defined(NV_C2C_UPPER_PD)/
s/$/#endif/
' file