我有一个文件,里面有这样的行:
"def{word} def{word}"
"def{worad} def{worads}"
我想报告出现两次的大括号单词。所以在这种情况下,输出应该只是"单词"我拥有的是:
#!/bin/bash
arr=(
"def{word} def{word}"
"def{worad} def{worads}"
)
for i in "${arr[@]}"; do
[[ $i =~ def{([a-z]+)}.*def{1} ]] || continue
echo ${BASH_REMATCH[1]}
done
即,我尝试将第一个单词与\1(反向引用)匹配。但是,输出为零。我该怎么做?
我发现 bash 正则表达式在括在引号中时表现得更好,即使你必须对此有点小心,因为直接引用会导致精确匹配而不是正则表达式匹配。 要解决此问题,您可以将正则表达式放在变量中,引号,然后在=~
表达式中引用它:
#!/bin/bash
arr=(
"def{word} def{word}"
"def{worad} def{worads}"
)
re="def{([a-z]+)}.*def{1}"
for i in "${arr[@]}"; do
[[ $i =~ $re ]] || continue
echo ${BASH_REMATCH[1]}
done
输出:
$ ./worad.sh
word
$
不过,这似乎只适用于 Bash v4。
使用 sed
sed -n '/({[^{]*}).*1/p' file
"def{word} def{word}"
如果只导出单词
sed -n 's/.*{([^{]*)}.*{1}.*/1/p' file
word
for bash中的循环真的很慢,这对于bash来说可能有点复杂。 我会为此推荐python或awk。 这里有一些 python 代码可以做你想做的事情:
#!/usr/bin/env python
import re
import sys
import itertools
def freq(alist):
counts = {}
for x in alist:
x = x[1:-1]
counts[x] = counts.get(x,0) + 1
return {m:[j[0] for j in n] for m,n in itertools.groupby(counts.iteritems(), lambda y: y[1])}
for line in sys.stdin:
counts = freq(re.findall(r'{[^}]*}', line))
if 2 in counts:
print ' '.join(counts[2])
else:
print
假设此脚本位于名为 two.py 文件中,如下所示运行:
cat yourfile | python two.py
现在它在python中,你有一些更容易扩展和维护的东西。
是的,有很多方法可以做到这一点,包括:
perl -lne '/def{(.+?)}.*def{1}/ and print $1' filename