有人能帮我解释以下 Linux Sed 命令吗?
sed -i '' 's#__OPENGL_LIBS__#-lGL -lGLU#' src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
我欣然承认,我发现 sed 命令语法非常晦涩难懂,而且阅读 sed 手册页到目前为止对我没有多大帮助。当我执行上述命令时,我收到此错误:
sed: can't read s#__OPENGL_LIBS__#-lGL -lGLU#: No such file or directory
因此,显然 sed 将第三个参数解释为文件名 - 这是要修改的文件吗?从 sed 手册页中,我看到这-I
意味着就地编辑目标文件。
第二个参数是空字符串""
- 手册页说这是“script-only-if-no-other-script”,但没有解释这是什么意思。最后一个参数src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
- 我知道前导s/
表示查找和替换,但这是什么src/
意思呢?
答案1
src/
正是应该所在的目录qt-mbgrdviz-3/qt-mbgrdviz-3.pro
。
Sed 命令相当简单,但是 — — 与大多数命令行一样 — — 看起来比实际上更复杂。
sed -i "" "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
-i
:表示对文件运行命令;也就是覆盖它。""
: 将是进行备份现场编辑时使用的文件扩展名。但正如手册页所述,“如果给出零长度扩展名,则不会保存任何备份。”这基本上意味着后面的内容-I
不是可选的。因此,""
有效地将该值设为零长度扩展名,因此不再保存备份。请注意,这是在 BSD(和 macOS)上使用的方式,而不是 Linux 使用的 GNU 工具;在这种情况下,-i
仅此而已就足够了。"s#__OPENGL_LIBS__#-lGL -lGLU#"
:在 Sed 中,模式中第一个后面的所有内容s
都用作分隔符。在这种情况下,它将用__OPENGL_LIBS__
的值替换任何/所有出现的-lGL -lGLU
。src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
:这只是要进行 Sed 处理的文件的完整路径。因此,当您输入什么src/
意思时,它只是应该包含 的目录路径qt-mbgrdviz-3/qt-mbgrdviz-3.pro
。
请注意,虽然此命令适用于安装在 macOS 等系统上的 BSD 版本的 Sed,但由于 ,它将在 GNU 系统上失败-i ""
。在 GNU 系统上,-i ""
应该像-i
这样:
sed -i "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
知道您的错误似乎是尝试使用 GNU 运行该命令的 BSD 变体。查看错误:
sed: can't read s#__OPENGL_LIBS__#-lGL -lGLU#: No such file or directory
有了这个多余的东西""
,GNU 上的 Sed 就会将其解释""
为 Sed 命令并认为这"s#__OPENGL_LIBS__#-lGL -lGLU#"
是文件路径。
额外的:在评论中你问:
“有人知道如何最好地编写使用 Sed 的可移植自动脚本吗?”
我不知道你的脚本的具体细节或目标,但是在我自己的 Bash 脚本中 - 我在 macOS 中开发,然后也在 Linux 系统上使用,在脚本顶部附近我有一段这样的代码:
#!/bin/bash -l
################################################################################
# Set script variables based on OS specific values.
if [[ "$OSTYPE" =~ ^darwin ]]; then
# For macOS
sed_options='-i ""';
else
# For Linux
sed_options='-i';
fi
然后 — 再次使用您的示例命令 — 我会执行如下操作:
sed ${sed_options} "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
请注意我如何用 替换了/ -i ""
。这样,我在 macOS 上编码时就可以专注于核心脚本编码,而不必担心 Linux 系统上出现问题。-i
${sed_options}