从 XARGS 每次迭代的输出中跳过第一行

从 XARGS 每次迭代的输出中跳过第一行
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用作管道:grepxargs

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'

相关内容