【问题标题】:run different pipelines on different column in bash在 bash 的不同列上运行不同的管道
【发布时间】:2015-07-02 20:17:03
【问题描述】:

我有一个包含文本消息的文件:1 行 = 一条消息。为了清理消息,我有一个可以像这样运行的管道:

cat file | ./clean.sh

但是现在,我需要对每条消息都关联到一个 ID 的文件做同样的事情,所以我的新文件是这种形式:

678 message1
456 message2
479 message3
...

该列是制表符分隔的。但我无法在其上运行 clean.sh 脚本,因为 ID + 选项卡将被清理程序删除(并且由于某些原因,我无法修改 clean.sh 脚本)。

如何在不修改 ID 的情况下创建一个可以清理消息的管道?或者,如何仅在特定列上运行管道?

我需要的输出是:

678 cleaned(message1)
456 cleaned(message2)
479 cleaned(message3)
...

编辑:

我最后做的是使用一个 FIFO 特殊文件,这样一切都保持为管道:

mkfifo col1 col2
tee > (cut -f1 > col1) > (cut -f2 | ./clean.sh > col2) > /dev/null;
paste -d'\t' col1 col2

【问题讨论】:

  • 您可以使用awkperl 或类似方法就地执行此操作(尽管为了简单起见,它可能需要至少每行运行一次清理程序)。如果您可以将文件拆分为列,然后重新加入,这会使事情变得更容易(您可以使用awkcut 拆分并使用paste 加入)。

标签: linux bash awk pipeline


【解决方案1】:

cutpaste。易于制表符分隔的文件。

cut -f1 file > file1
cut -f2- file | clean.sh > file2
paste file1 file2 > clean-file

对于输入流版本,这是作弊吗?

... | | (cat > foo ; paste <(cut -f1 foo) <(cut -f2- foo | ./clean.sh))

【讨论】:

  • 谢谢,这基本上就是我所做的。我只是在文件中使用了 FIFO 而不是 cat,因为这会阻塞。
【解决方案2】:

类似于@mob 的回答,但使用进程替换而不是临时文件:

paste $<(cut -f1 file) $<(cut -f2- file | clean.sh)

如果输入的是流而不是文件,你可以逐行读取并在每一行调用clean.sh

cat file | while read -r num line; do
    echo "$num" "$(echo "$line" | clean.sh)"
done 

【讨论】:

  • 感谢 mob 和 Barmar。是的,这基本上就是我想要做的。但是,当带有消息的文件不可用时,有没有办法做类似的事情,比如如果我在流中获得了这个文件?更具体地说,创建一个脚本 f.sh,例如 "cat file | ./f.sh" 输出带有 ID 的清理文件?
  • 我已经通过阅读每一行并在其上调用clean.sh 来展示如何做到这一点。
猜你喜欢
  • 2020-08-09
  • 2016-12-24
  • 1970-01-01
  • 2012-02-23
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多