Linux 和 Solaris 的通用 grep 方法
Universal approach to grep for both Linux and Solaris
我有一个相对较长的脚本集合,我目前正在评估这些脚本,并对源代码进行更改以便在 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...]
如何将类似的东西放在脚本的顶部:
[ -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 grep
).因此,只需将该目录添加到 $PATH
的开头,使其具有最高优先级。
一个解决方案是在 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
Is there a way to write a single statement in Bash to work in both scenarios?
是的。
Or, should I be mentally prepared to start implementing additional if/else statements for each operating system?
不,应该尽可能避免这种情况。在您的情况下,一切都可以使用标准命令完成,因此无需添加 OS 特定代码。
这是一种可移植的方法。这应该适用于所有类似 Unix 的机器:
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>\'
getconf PATH
正在向所有 Unix/Unix 类似实现的 POSIX 兼容命令返回路径。
printf
应该在需要格式化命令时使用,echo
不能可靠地使用,因为它的行为未定义,即使在 POSIX 下也是如此。
\<...\>
是 POSIX 使用扩展正则表达式指定单词边界的方法。
请注意,我没有使用 $(getconf PATH)
,而是使用较旧的 `getconf`
语法,因为在 Solaris 10 上,您可能 运行 遗留的 Bourne shell。
我有一个相对较长的脚本集合,我目前正在评估这些脚本,并对源代码进行更改以便在 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...]
如何将类似的东西放在脚本的顶部:
[ -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 grep
).因此,只需将该目录添加到 $PATH
的开头,使其具有最高优先级。
一个解决方案是在 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
Is there a way to write a single statement in Bash to work in both scenarios?
是的。
Or, should I be mentally prepared to start implementing additional if/else statements for each operating system?
不,应该尽可能避免这种情况。在您的情况下,一切都可以使用标准命令完成,因此无需添加 OS 特定代码。
这是一种可移植的方法。这应该适用于所有类似 Unix 的机器:
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>\'
getconf PATH
正在向所有 Unix/Unix 类似实现的 POSIX 兼容命令返回路径。
printf
应该在需要格式化命令时使用,echo
不能可靠地使用,因为它的行为未定义,即使在 POSIX 下也是如此。
\<...\>
是 POSIX 使用扩展正则表达式指定单词边界的方法。
请注意,我没有使用 $(getconf PATH)
,而是使用较旧的 `getconf`
语法,因为在 Solaris 10 上,您可能 运行 遗留的 Bourne shell。