例如,文件a.txt
:
/abc
/abc/def
/abc/xyz
/abcd
/fghi
给出的输入和预期结果是:
/abc/dog => /abc
/abc/def12 => /abc/def
/dog => (NONE)
仅使用 shell 命令或grep
、sed
、awk
等等可以实现吗?
答案1
一种方法是稍微反转一下输入的概念,并将其用作a.txt
要搜索的模式,而你所说的“输入”(我称之为“file2”)就是要搜索的内容在:
grep -o -f a.txt file2
或者
echo "/abc/dog" | grep -o -f a.txt
echo
尽管该版本将具有非零的返回代码,但这些不会为“/dog”输出任何内容。
编辑:
这将更紧密地匹配您请求的输出:
while read -r line
do
match=$(echo "$line" | grep -of a.txt)
match=${match:-(NONE)}
printf "%-12s => %s\n" "$line" "$match"
done < file2
您可以强制搜索模式从行首开始,如下所示:
grep -o -f <(sed 's/^/^/' a.txt) file2
答案2
听起来像是 Perl 的工作,所以这里有一个 awk 解决方案。经过最低限度的测试。
#!/bin/sh
prefixes_file=$1
shift
awk -vprefixes_file="$prefixes_file" '
BEGIN {
while (getline <prefixes_file) { ++prefixes[$0]; }
}
{
for (n = length; n >= 0; --n) {
if (prefixes[substr($0,1,n)]) {
print $0, "=>", substr($0,1,n);
break;
}
}
if (n == -1) { print $0, "=>", "(NONE)"; }
}' "$@"
答案3
一个简单的 shell 脚本就可以完成这个工作:
#!/bin/sh
query=$1
file=$2
for i in $(seq 1 ${#query})
do
current_query=$(echo $query | cut -b1-$i)
grep -q "$current_query" "$file" || break;
longest_match=$current_query
done
echo "$longest_match"
你可以像这样使用它:
longest_match.sh '/abc/dog' a.txt
它将打印/abc/dog
在文件 a.txt 中找到的查询的最长匹配,即/abc/d