我在一个文件中有一个字符串列表。我想找出添加到特定前缀时哪些字符串在另一个文件中不存在。
所以如果字符串列表是这样的
foo
bar
baz
qux
目标文件是这个
prefix-foo
prefix-barnotreally
prefix-baz
命令的输出应为
bar
qux
我知道-f
grep 标志,但据我所知,它不允许用户仅将文件中的字符串用作模式的一部分
> 另一种选择是使用标准的Unix工具join
:
join -t- -1 1 -2 2 -v 1 <(sort file1) <(sort -t- -k 2 file2)
该命令在某个联接字段上联接两个表。 它要求两个文件按连接字段排序,这就是我们需要两个排序命令的原因。 我们还可以通过使用临时文件使其更具可读性:
sort file1 > file1.sorted
sort -t- -k 2 file2 > file2.sorted
join -t- -1 1 -2 2 -v 1 file1.sorted file2.sorted
第一个sort
命令只是对文件的行进行排序。 第二个排序命令按第二个字段(-k 2
(排序,使用破折号作为字段分隔符(-t-
(。
join
命令还指定-
作为字段分隔符 (-t-
(,并选择第一个文件中的第一列作为连接键 (-1 1
(,选择第二个文件中的第二列 (-2 2
(。 输出仅限于第一个文件 (-v 1
( 中不可配对的行。
如果您的文件非常大,则此解决方案比其他任何解决方案都更有效,但在大多数实际情况下,性能差异并不重要。
您可以使用进程替换从第二个文件中提取要传递给grep
-f
选项的字符串部分:
grep -vxFf <(cut -f2- -d- file2) file1
-v
- 反转搜索;查找不匹配的行-x
- 匹配整条线-F
- 查找字符串,而不是正则表达式<(cut -f2- -d- file2)
- 从目标文件中提取字符串,留下前缀
您可以使用 bash 脚本,该脚本接收包含该格式字符串的文件作为第一个参数,并将该格式的文本文件作为第二个参数接收
#! /bin/bash
if [ $# -ne 2 ]; then
echo "Usage: $0 <file1> <file2>"
exit 1
fi
fStrings=$1
file=$2
while read string; do
cat $file | grep -qw $string
if [ $? -ne 0 ]; then
echo $string
fi
done < $fStrings
如果您熟悉awk,则可以使用它。下面是一个示例:
$ cat test.data
prefix-foo
prefix-barnotreally
prefix-baz
$ cat test.awk
BEGIN {
split("foo bar baz qux", a);
}
/^prefix-*/ {
gsub("^prefix-", "");
for (i in a)
if ($0 == a[i])
found[$0] = ""
}
END {
for (i in a)
if (!(a[i] in found))
print a[i]
}
$ awk -f test.awk test.data
bar
qux
with awk
awk 'NR==FNR{a=a " " $0;next} ! match(a,"\<"$0"\>")' targetfile liststrings
获取字符串 a 中的所有目标文件,而不打印在字符串 a 中找到的列表字符串行