构建R软件包时,该命令将处理步骤输出到std out。从该输出中,我想捕获包的最终名称。
在下面的模拟脚本中,我显示了build命令的输出。需要捕获的部分是从building
开始的最后一行。
如何获取与这些引号匹配的正则表达式,然后将包名称捕获到变量中?
#!/usr/bin/env bash
var=$(cat <<"EOF"
Warning message:
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘analysis’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
Removed empty directory ‘analysis/.idea/inspectionProfiles’
Removed empty directory ‘analysis/.idea/snapshots’
* creating default NAMESPACE file
* building ‘analysis_0.1.tar.gz’
EOF
)
regex="building [\u2018](.*?)?[\u2019]"
if [[ "${var}" =~ $regex ]]; then
pkgname="${BASH_REMATCH[1]}"
echo "${pkgname}"
else
echo "sad face"
fi
这在macOS和CentOS上都应该起作用。
答案 0 :(得分:1)
有很多方法可以做到这一点,
file=`echo "$var" | grep '^\* building' | grep -o '‘.*’' | head -c -4 | tail -c +4`
echo $file
* building
(第一个grep)开头的行‘’
(第二个grep)之间查找文本答案 1 :(得分:1)
在Bash 4.2中引入了对\u
和\U
Unicode转义的支持。 CentOS 7具有Bash 4.2,因此可以在该平台上运行:
regex=$'.*building[[:space:]]+\u2018(.*)\u2019'
不幸的是,早期版本的CentOS具有较旧的Bash版本,我相信MacOS上Bash的默认版本仍为3.2。对于这些,假设引号编码为UTF-8,这应该可以工作:
regex=$'.*building[[:space:]]+\xe2\x80\x98(.*)\xe2\x80\x99'
如果引号在不同的平台上以不同的方式编码,则可以使用交替(例如,用(\xe2\x80\x98|...)
代替xe2\x80\x98
)来匹配所有可能性(并调整用于{{ 1}})。
有关Bash中Unicode的更多信息,请参见How do you echo a 4-digit Unicode character in Bash?。
我使用BASH_REMATCH
来设置正则表达式,因为它支持$'...'
并且(从Bash 4.2起)支持\x
转义字符,而Bash不支持正则表达式。
关于正则表达式:
\u
是为了确保匹配出现在文本的末尾。.*
,因为它们与Bash的内置正则表达式不兼容。有关Bash正则表达式的信息,请参见mkelement0's excellent answer至How do I use a regex in a shell script?。