2016-02-04 44 views
0

我在Stack Overflow上搜索了几个问题和答案,但是它们都不适用于我的情况,我不知道为什么我的正则表达式不起作用。如果你能指出我错误的想法,我会非常感激。从一行中找到确切的单词并用grep/sed删除那一行

测试用例:文本文件包含

AllenZhou:9175186661:111th 1111 NY, 11111 
XiaoyuZhou:9175186662:2222 222th 22222 NY 22222 
Allen:1231231234:abc rd, PA 

这里是我的功能:

checkEntry(){ 
    vaildName=true 
    while read entry 
    do 
      if $(echo $entry | grep --quiet $name)//$name read from keyboard 
      then 
        vaildName=false 
      fi 
    done < $fileName 
} 

如果我进入Zhou,我的函数将返回两个AllenZhou,并XiaoyuZhou。我做了小的研究之后,我改变了grep命令参数

if $(echo $entry | grep --quiet ^$name:$) 

事实证明,它从来没有发现任何东西AllenZhouXiaoyuZhou –我很困惑。

sed -i -n /$name/d $fileName 

这是我用来删除包含字符串模式的行的代码。问题和grep一样,如果我输入ZhouAllen,该命令将删除包含关键字的两行。但是,当我改变

sed -i -n /\<$name\>/d $fileName 

它不会删除AllenZhouXiaoyuZhouZhou ...我再一次感到困惑。

+0

根据您的样本输入(编辑您的Q),请显示您的预期输出。并指明哪个搜索目标。也许你将不得不使用'sed'/ AllenZhou/d''。谢谢,祝你好运。 – shellter

+0

'sed -i -n/pattern/d'将会删除你的文件 - 可能不是你想要的! –

+1

谷歌外壳的引用惯例很快,因为你需要引用你的变量默认情况下,如果你有一个特定的目的,这样做,并完全理解所有的影响,只留下他们不加引号。如果你不开始引用你的变量,你很快会看到一些奇怪的,危险的影响。 –

回答

2

if中使用命令替换不符合您的想法。您正在捕获grep的输出 - 其中-q选项始终为空字符串 - 并且作为参数传递给if,该参数需要命令名或管道作为其参数。它基本上试图执行空字符串,这当然不会做任何有用的事情(最终效果是if条件将总是成功)。

你想简单地

if echo "$entry" | grep -q "$name"; then 
    : stuff 
fi 

以上惯用和高效

if [[ "$entry" = *"$name"* ]]; then 
    : stuff 
fi 

甚至

case $entry in *"$name"*) 
    : stuff;; 
esac 

(双括号[[ ... ]]都是Bash而已,而case可以移植到任何POSIX shell,甚至连原来的Bourne shell。单方括号也是便携式的,他们可以做... 东西这样,但它比你想要的更丑,更脆,更复杂。)

还要注意报价。包含任意字符串的变量needs to be quoted

另一方面,您希望使用read -r - 如果没有选项,read的行为会带来一些令人讨厌的遗留行为,以便在某些特定情况下实现历史向后兼容性。

但是,分别检查每条线只是麻烦。整个功能可能是

grep -q "$name" "$fileName" 

它也返回实际结果;你的函数没有做到的事情(除了设置一个全局变量,如果这就是它的作用 - 很难从上下文中看出来。即使在shell脚本中,在函数中使用全局变量也是一个坏主意)。

也许你会想要一些正则表达式锚定来限制匹配到第一个字段。 grep "^[^:]*$name"在第一个冒号前的任何地方寻找匹配。

数据中没有词语边界(空格,标点符号等),只是大小写的变化,所以\<\>无法匹配这些名称。观察你的大小写模式,也许你想在比赛结束后要求大写字母或冒号; "^[^:]*$name[[:upper:]:]"

如果最终目标是提取地址或电话号码,那就直接做。你需要Awk而不是grep

awk -F : -v name="$name" 'BEGIN { pat = name "($|[[:upper:]])"; result = 1 } 
    $1 ~ pat (print $2; result = 0 } 
    END { exit result }' "$fileName" 

awk的脚本打印第二场从任何匹配线集的结果代码,这样就可以在一个或if条件while使用它。

相关问题