![根据另一个文件中找到的行从文件中删除行](https://linux22.com/image/71112/%E6%A0%B9%E6%8D%AE%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%E6%89%BE%E5%88%B0%E7%9A%84%E8%A1%8C%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E8%A1%8C.png)
文件 file1.txt 包含如下行:
/api/purchase/<hash>/index.html
例如:
/api/purchase/12ab09f46/index.html
文件 file2.csv 包含如下行:
<hash>,timestamp,ip_address
例如:
12ab09f46,20150812235200,22.231.113.64
a77b3ff22,20150812235959,194.66.82.11
我想过滤 file2.csv,删除 file1.txt 中也存在哈希值的所有行。也就是说:
cat file1.txt | extract <hash> | sed '/<hash>/d' file2.csv
或类似的东西。
它应该很简单,但我似乎无法使其发挥作用。
任何人都可以提供此任务的工作管道吗?
答案1
cut -d / -f 4 file1.txt | paste -sd '|' | xargs -I{} grep -v -E {} file2.csv
解释:
cut -d / -f 4 file1.txt
将从第一个文件中选择哈希值
paste -sd '|'
将把所有哈希值连接成一个正则表达式 ex。H1|H2|H3
xargs -I{} grep -v -E {} file2.csv
将使用先前的模式作为参数调用 grep,xargs 将替换{}
为STDIN
如果你没有,paste
你可以用它替换它tr "\\n" "|" | sed 's/|$//'
答案2
可能的awk
解决方案:
awk 'NR == FNR { x[$4] = 1; next; } { if (!($1 in x)) print $0; }' FS="/" file1.txt FS="," file2.txt
首先,我们file1.txt
使用FS
(字段分隔符)“/”进行读取,并使用字段中的键值创建数组 x ,$4
该字段是您想要的哈希值。接下来,我们读取第二个文件file2.txt
设置FS
,,
并检查字段值是否$1
不作为数组中的键存在x
,如果不存在,我们将其打印出来。
评论中提出的更惯用的说法可能是:
awk 'NR == FNR { x[$4] = 1; next; } !($1 in x)' FS="/" file1.txt FS="," file2.txt
答案3
为了GNU sed
sed -z 's%.*/\([^/]*\)/index.html\n%\1\\|%g;s%^%/%;s%\\|$%/d%' file1.csv |
sed -f - file2.csv
在哪里第一的 sed以 sed-command-format 生成哈希列表,/12ab09f46\|a77b3ff22\|..../d
并将其传输到下一个 sed-script 从输入中读取上述命令,因此-f -
选项。
与相同grep
grep -oP '[^/]*(?=/index.html$)' file1.csv | grep -Fvf - file2.csv
或者没有 perl 表达式:
grep -o '[^/]*/index.html$' file1.csv |
grep -o '^[^/]*' |
grep -Fvf - file2.csv
甚至更好切:
cut -d/ -f4 file1.csv | grep -Fvf - file2.csv
答案4
我刚刚尝试了以下一种衬里,它似乎可以完成这项工作:
for i in `cat file1.txt | awk -F"/" '{print $4}'`; do echo "\n $i" ; sed -ri "/^$i,/d" file2.csv ; done
请先更换-里和-关于来测试它。-关于进行一次试运行,如果一切正常,您可以运行它-里