grep 查找一行中的文本。但如果它仅在开头有注释,则将其从 grep [重复] 中排除

grep 查找一行中的文本。但如果它仅在开头有注释,则将其从 grep [重复] 中排除

我正在尝试在 /etc/oratab 中 grep 查找实例“test”。但只想显示不以注释开头的行。以下是 /etc/oratab 文件中的行:

#test:/u01/appl/oracle/test/db/tech_st/12.1.0.2:N
test:/b001/app/oracle/testrac/db/tech_st/12.1.0.2:N         # line added by Agent

这就是我试图获取我感兴趣的详细信息的方式(将以下内容放在 shell 脚本中:

DB_NAME=test
env_var=`cat /etc/oratab |grep $DB_NAME |grep -v '#' |cut -d":" -f 2`
echo $env_var

这里的问题是,由于第二行末尾也有注释,因此它也被忽略。

请帮忙。

问候, RA

答案1

awk这里会是一个更好的选择:

DB_NAME=test; export DB_NAME
file=$(awk -F: '$1 == ENVIRON["DB_NAME"] {print $2; exit}' < /etc/oratab)

printf '%s\n' "$file"

在 Solaris 上,请确保执行以下操作:

PATH=$(getconf PATH):$PATH

(并#! /usr/xpg4/bin/sh -在 Solaris 10 及更早版本上使用 if )以获得标准实用程序。或者使用command -p awk.否则,您可能会得到awk70 年代的陈旧产品。

答案2

比使用 awk 重写它更简单的解决方案是添加一个简单的 ^ 来指示行的开头:

env_var=`cat /etc/oratab |grep $DB_NAME |grep -v '^#' |cut -d":" -f 2`

删除grep -v '^#'所有以 # 开头的行并且通常很有用。

答案3

使用sed,您可以将greps 和 the组合cut在一次传递中:

sed "/^$DB_NAME:/! d;s///;s/:.*//" /etc/oratab

  • /^$DB_NAME:/选择以;$DB_NAME开头的所有行:反转!匹配,因此以下d删除了与此模式不匹配的所有行
  • s///删除最后一个匹配项,在本例中test:
  • s/:.*//删除:以及以下所有内容

答案4

其他答案适用于该示例(文件是 CSV*(冒号分隔值),搜索字符串将是第一个字段,所需输出是第二个字段),但这些约束/条件实际上都不是指出在问题中。而且,虽然问题要求一个排除以下行的命令开始带有评论,这可能不是OP真正想要的。 (像这样的行怎么样unwanted line:blah:blah #test,其中包含test 在评论中?)OP想要的答案是

grep '^[^#]*test' /etc/oratab

或者

grep "^[^#]*$DBNAME" /etc/oratab

它搜索出现的行test,并且它之前的所有字符都不是#

像往常一样,您应该始终引用您的 shell 变量引用(例如,"$DB_NAME""$env_var"),除非您有充分的理由不这样做,并且您确定您知道自己在做什么。和,正如斯特凡·查泽拉斯 (Stéphane Chazelas) 指出的,如果$DBNAME看起来像一个不平凡的正则表达式(例如,它包含.*[... ]),可能会出现不需要的结果。

相关内容