cut -d, -f2 parsed_repayment.csv | uniq -d | xargs -n1 -I{} grep {} parsed_repayment.csv | wc -l
我基本上想跳过每个 grep 命令的第一个匹配并将它们写入文件,但 xargs 合并了所有输出。有没有一些方便的方法来实现这一目标?
例如,假设我有一个单词“狗”、“猫”、“马”的列表。我想使用 grep 搜索文件中的所有三个单词。现在假设文件包含每个单词 2 个匹配行 -
dog l1
dog l2
cat l1
cat l2
horse l1
horse l2
我期望的输出是 -
dog l2
cat l2
horse l2
对于搜索的每个单词,我希望它跳过第一个匹配项。此外,每个单词可以有不同数量的匹配。
我尝试将 grep 之后的输出写入临时文件,然后使用 tail 命令剪切第一行,但由于 xargs 一起传递所有给定单词的匹配项,我无法跳过单个单词的第一个匹配项。
答案1
听起来像是一个XY问题而你真正想要的:
awk -F, '$2 == prev; {prev = $2}' < parsed_repayment.csv
即,报告第二个字段与前一行的第二个字段相同的行。
对于您所问的问题的答案,而不是您真正想要的答案,将是:
cut -d, -f2 parsed_repayment.csv |
uniq -d |
xargs sh -c '
for i do
grep -e "$i" parsed_repayment.csv | tail -n +2
done' sh
但这有一些注意事项:
xargs
需要非常具体的输入格式。如果第二列的值包含空格、单引号、双引号或反斜杠,则无法正常工作。grep
明白$i
作为正则表达式。即使您使用-F
或这些字符串不包含正则表达式运算符(例如.
,$
...),grep
也会在行中的任何位置查找这些字符串,而不仅仅是在第二个领域,更不用说完全一样第二个字段。
答案2
您可以像这样在内部sed -e 1d
用作管道:grep
xargs
xargs -n1 -I{} bash -c 'grep {} apt-installed |sed -e 1d'
所以最后:
cut -d, -f2 parsed_repayment.csv | uniq -d | xargs -n1 -I{} bash -c 'grep {} apt-installed |sed -e 1d' | wc -l
答案3
以下将第一个输入行写入 file foo
,并回显其余部分:
read line ; echo "$line" >> foo ; while read line ; do echo "$line" ; done
测试例如这样:
seq 0 9 | ( read line ; echo "$line" > foo ; while read line ; do echo "$line" ; done )
cat foo
现在,不是grep
直接在 中执行xargs
,而是执行一个管道,将 的输出放入grep
上面的片段中。这解决了xargs
连接所有输出的问题。
整个事情足够长,我会考虑将片段放入 shell 脚本中,尤其是。如果你想控制文件名。
编辑
这假设您想将已跳过的条目写入文件,并将其余条目写入标准输出,但也许我理解错误了。
答案4
使用 GNU Parallel 时,它看起来像这样:
cut -d, -f2 parsed_repayment.csv | uniq -d |
parallel 'grep {} parsed_repayment.csv | tail -n +2'