我试图将 sed 命令的结果分配给 bash 中的变量,但我无法正确转义所有内容(可能只是由于我缺乏 bash 知识),我尝试过:
hash_in_podfile=$( sed -rn 's/^ *pod [\'\"]XXX["\'],.*:commit *=> *["\']([^\'"]*)["\'].*$/\1/p' ${PODS_PODFILE_DIR_PATH}/Podfile )
但我越来越
bash_playground.sh:第 9 行:寻找匹配的“”时出现意外的 EOF
更新的脚本
这是我正在使用的脚本,已使用答案中的代码进行更新。仅路径和注释发生了变化:
#!\bin\sh
PODS_PODFILE_DIR_PATH='/Users/path/to/file'
# just a comment
hash_in_podfile=$(sed -rnf - <<\! -- "${PODS_PODFILE_DIR_PATH}/Podfile"
s/^ *pod ['"]XXX["'],.*:commit *=> *["']([^'"]*)["'].*$/\1/p
!
)
echo $hash_in_podfile
执行与sh script_name.sh
sh --version
产量:
GNU bash,版本 3.2.57(1)-release (x86_64-apple-darwin20) 版权所有 (C) 2007 Free Software Foundation, Inc.
执行时我得到:
script_name.sh: line 6: unexpected EOF while looking for matching `"'
script_name.sh: line 10: syntax error: unexpected end of file
答案1
您的脚本中有两个问题:
macOS 上的shell
sh
是一个非常旧的版本bash
,它有一个错误,会阻止您在命令替换中的此处文档中使用不平衡引号:$ a=$( cat <<'END' > " > END > ) > sh: unexpected EOF while looking for matching `"'
(我必须在最后按Ctrl+D。
)
)您可以通过从 Homebrew 包管理器(或等效工具)安装较新的 shell 或在 macOS 上
bash
使用shell来解决此问题。zsh
macOS
sed
上没有这个-r
选项。要在sed
macOS 上使用扩展正则表达式,请使用-E
(现在 GNU 也支持sed
)。不过,您的表达式不使用扩展正则表达式功能,因此只需删除该选项也可以。 macOSsed
也不能用作-
选项参数来-f
表示“从标准输入读取”。代替使用/dev/stdin
。
建议:
#!/bin/zsh
PODS_PODFILE_DIR_PATH='/Users/path/to/file'
# just a comment
hash_in_podfile=$(sed -n -f /dev/stdin -- $PODS_PODFILE_DIR_PATH/Podfile <<'END'
s/^ *pod ['"]XXX["'],.*:commit *=> *["']([^'"]*)["'].*$/\1/p
END
)
echo $hash_in_podfile
如果您只想输出值,则不要使用中间变量:
#!/bin/zsh
PODS_PODFILE_DIR_PATH='/Users/path/to/file'
# just a comment
sed -n -f /dev/stdin -- $PODS_PODFILE_DIR_PATH/Podfile <<'END'
s/^ *pod ['"]XXX["'],.*:commit *=> *["']([^'"]*)["'].*$/\1/p
END
答案2
如果该heredoc
方法不适用于您的系统,那么您可以选择通过 shell 变量提供 sed 命令的替代方案:
hash_in_podfile=$(q=\"\'; sed -ne "s/^ *pod [$q]XXX[$q],.*:commit *=> *[$q]([^$q]*)[$q].*\$/\\1/p" -- "${PODS_PODFILE_DIR_PATH}/Podfile")
尽管有很多方法可以做到这一点,但最简单的方法是通过引用的heredoc在stdin上提供sed命令,这样就不需要转义对shell有意义的sed字符。
hash_in_podfile=$(sed -rnf - <<\! -- "${PODS_PODFILE_DIR_PATH}/Podfile"
s/^ *pod ['"]XXX["'],.*:commit *=> *["']([^'"]*)["'].*$/\1/p
!
)
答案3
hash_in_podfile="$( sed -rn 's/^ *pod ['\''"]XXX["'\''],.*:commit *=> *["'\'']([^'\''"]*)["'\''].*$/\1/p' "${PODS_PODFILE_DIR_PATH}/Podfile" )"
基本的“技巧”是在单引号内“转义”单引号的方式:echo 'before'\''after'
yields before'after
。考虑到 Bash 扩展的工作方式,这将形成一个单一的令牌,正如预期的那样。等效的选项是echo 'before'"'"'after'
,但前一个语法稍微短一些。
要检查扩展命令是否正确,只需将其打印出来:
echo sed -rn 's/^ *pod ['\''"]XXX["'\''],.*:commit *=> *["'\'']([^'\''"]*)["'\''].*$/\1/p' "${PODS_PODFILE_DIR_PATH}/Podfile"
顺便说一句,最好使用最新的软件(例如,Bash 的版本为 5.1.8),而不是严重过时的版本。在某些情况下,巨大的版本差异可能会导致问题难以重现并且建议难以遵循。