【问题标题】:Print all pairs of values in column of tsv file via bash通过 bash 打印 tsv 文件列中的所有值对
【发布时间】:2020-04-07 09:28:32
【问题描述】:

我想编写一个小的 shell 脚本来让自己更轻松地完成标记任务。唉,我仍然缺乏这样做的技能。

我有一个如下所示的 news.tsv 文件:

id  foo  bar text 
1   a    b   lorem
2   c    d   ipsum
...
50  e    f   muspi

文本列中的实际条目是冗长的新闻文章。我想一次打印 2 个这样的文本,直到列中所有可能的对都打印完。

在寻找解决方案时,我发现 awk 可能是完成这项任务的正确工具。我知道如何在文本列中打印两个特定条目,例如,

awk -F '\t' 'NR==2 {print $4} NR==3 {print $4}' news.tsv

将打印 lorem 和 ipsum。为了获得所有对,我想我需要一个嵌套的 for 循环,但我无法用 awk 实现它。

我的意大利面尝试看起来像这样:

awk -F '\t' '{for (i=0; i<50; i++){for (j=i+1; j<50; j++) if(i!=j){NR==i {print $4} NR==j {print $4}}}}' news.tsv

我也愿意使用其他工具。

【问题讨论】:

  • 你的“意大利面条代码”能做到你想要的吗?
  • text 可以包含tabs 吗?你说长篇文章——你有什么保证文本中没有其他标签?
  • 2 of these texts at once, until all possible pairs in the column have been printed 这是什么意思?你能发布你期望得到的示例输出吗?
  • 你能得到想要的输出吗?
  • 输出对的顺序重要吗?我的意思是,如果您打印foo bar,那么您是否也应该打印bar foo

标签: linux bash loops awk


【解决方案1】:

这是你想要的吗?

awk 'NR>1 {print $4; next; print $4}'

【讨论】:

    【解决方案2】:

    这是基于您自己的脚本的尝试...假设永远没有嵌入式 TAB。

    $ cat awkward 
    NR>1{
      a[NR-1]=$4
    }
    END{
      for(i=1;i<=50;i++){
        for(j=1;j<=50;j++){
          if(i!=j){
            print a[i],a[j]
          }
        }
      }
    }
    

    像这样调用:

    $ awk -f awkward test.tsv
    Lorem ipsum
    Lorem dolor
    Lorem sit
    Lorem amet,
    Lorem consectetur
    Lorem adipiscing
    Lorem elit,
    Lorem sed
    Lorem do
    Lorem eiusmod
    .
    .
    [over 2000 lines stripped]
    .
    .
    fugiat dolor
    fugiat in
    fugiat reprehenderit
    fugiat in
    fugiat voluptate
    fugiat velit
    fugiat esse
    fugiat cillum
    fugiat dolore
    fugiat eu
    

    【讨论】:

    • @Gripe - 你接受的答案不尊重if(i!=j) ...只是把它放在那里。
    • 嗨@tink,我可能调用错了,但对我来说,这似乎是在第 7 个位置打印一对单词,而不是 tsv 中第 7 个字段的一对值。
    • 我的脚本基于呈现的输入;如果这不是您真正拥有的,并且在第四个之前的任何字段中都有空格,我们可以轻松调整调用awk -F'\t' -f awkward test.tsv
    • @tink 在我的代码中,ji+1 开始,并且不需要条件if(i!=j)N 项中的combination 个数可以通过N * (N-1) / 2 计算。您的答案同时生成lorem ipsumipsum lorem(以及更多...)。我认为这不是 OP 想要的。
    【解决方案3】:

    如果文本的总量不是那么大,那将是高效的 将整个文本存储在一个数组中。否则你需要读取输入文件 多次(组合次数)。

    那么怎么样:

    awk -F '\t' '
        NR>1 {texts[++n]=$4}
        END {
            for (i=1; i<n; i++) {
                for (j=i+1; j<=n; j++) {
                    print texts[i] " " texts[j]
                }
            }
        }' news.tsv
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-07-29
      • 2018-04-23
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 2014-05-04
      • 2012-07-04
      • 1970-01-01
      相关资源
      最近更新 更多