我目前正在评估相对较长的脚本集合,并对源代码进行更改,以便在Linux和SunOS框中执行相同的脚本集。部分代码有一个简单的grep:
#Linux
echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
如果翻译为:
,我的移植尝试工作正常#SunOS
echo -e "\n foo \n bar \n test ok" | /usr/xpg4/bin/grep -Ev 'foo|bar'
有没有办法在Bash中编写单个语句才能在两种情况下都能工作?或者,我是否应该做好心理准备,为每个操作系统开始实现额外的if / else语句?
在这种情况下,似乎/ bin / grep可以同时执行正则表达式和单词匹配,但是使用/ usr / bin / grep我们只能执行单词而不是两者:
$ echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
grep: illegal option -- E
Usage: grep [-c|-l|-q] -bhinsvw pattern file . . .
$ echo -e "\n foo \n bar \n test ok" | /usr/xpg4/bin/grep -Evw 'foo|bar'
Usage: grep [-c|-l|-q] [-bhinsvwx] pattern_list [file ...]
grep [-c|-l|-q] [-bhinsvwx] [-e pattern_list]... [-f pattern_file]... [file...]
grep -E [-c|-l|-q] [-bhinsvx] pattern_list [file ...]
grep -E [-c|-l|-q] [-bhinsvx] [-e pattern_list]... [-f pattern_file]... [file...]
grep -F [-c|-l|-q] [-bhinsvx] pattern_list [file ...]
grep -F [-c|-l|-q] [-bhinsvx] [-e pattern_list]... [-f pattern_file]... [file...]
答案 0 :(得分:3)
如何将类似的内容放在脚本的顶部:
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin:$PATH"
然后以下行将适用于两个系统:
echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
当然,我们的想法是检查目录/usr/xpg4/bin
是否存在,如果存在,我们可以假设它包含一个支持我们想要的选项的grep
(可能是GNU {{1} }})。所以只需在grep
的开头添加该目录,以便它具有最高优先级。
答案 1 :(得分:3)
有没有办法在Bash中编写单个语句才能在两种情况下都有效?
是
或者,我是否应该做好心理准备,为每个操作系统开始实现额外的if / else语句?
不,如果可能,应该避免这种情况。在您的情况下,可以使用标准命令完成所有操作,因此无需添加特定于操作系统的代码。
这是一种可移植的方式。这应该适用于所有类似Unix的机器:
sigmoid
PATH=`getconf PATH`:$PATH # Should be done once at the beginning of scripts.
printf "\n foo \n bar \n test ok" | grep -Ev '\<foo\>|\<bar>\'
在所有Unix / Unix类实现上返回PATH到POSIX兼容命令。
getconf PATH
,printf
无法可靠地使用,因为其行为未定义,即使在POSIX下也是如此。
echo
是使用扩展正则表达式指定单词边界的POSIX方法。
请注意,我没有使用\<...\>
,而是使用较旧的$(getconf PATH)
语法,因为在Solaris 10上,您可能正在运行旧版Bourne shell。
答案 2 :(得分:0)
一个解决方案是放在 shebang 之后:
grep_path=/usr/lib/gnu/bin # <- EDIT ME
PATH=$grep_path:$PATH
# will work on any platform with a GNU grep
grep foobar file