【问题标题】:Unix: Append each element of a second column to each element of the firstsUnix:将第二列的每个元素附加到第一列的每个元素
【发布时间】:2019-11-17 06:42:42
【问题描述】:

我不是经验丰富的程序员,我无法找到解决以下问题的方法。如果我措辞不正确,请见谅(这可能是我搜索的问题)

我有两个单列文件

A
B
C

X
Y
Z

我想创建一个文件,将第二列的每个元素附加到第一列的每个元素以获取:

AX
AY
AZ
BX
BY
BZ
CX
CY
CZ

结果的顺序并不重要(例如,AX、BX、... 就可以了)。

我看到的大多数示例都使用剪切和粘贴,但这只是我正在寻找的部分解决方案。

我对任何方法都持开放态度,但如果可以在 bash shell 中实现,我更愿意这样做。

非常感谢。

JPG

【问题讨论】:

  • edit 你的问题显示简洁、可测试的示例输入和预期输出,使用编辑器格式化{} 按钮以提高可读性。如果您的输入是行分隔的,那么不要显示它以逗号分隔并告诉我们它的行分隔 - 显示它是行分隔的。我们需要您提供输入/输出,我们可以按原样复制/粘贴以测试潜在的解决方案。
  • 当你说if it’s possible to do it in the bash shell I would prefer that. - 你的意思是使用 bash 内置函数(如果是,为什么?)或使用标准 UNIX 命令,如 grep、sed、awk 等或其他什么?
  • @jpg 请检查我的编辑是否符合您的意图。 @Léa 处理IFS 的解决方案似乎是基于对您的问题设置的误读
  • 我提交答案后问题设置发生了变化。

标签: bash unix cartesian-product


【解决方案1】:

使用jq 的另一种解决方案 有一个好处......它从两个输入文件中过滤掉空行

jq -rn --rawfile f1 file1.txt --rawfile f2 file2.txt 
  'def seq: split("\n")[] | select(length > 0);
   {a: $f1|seq, b: $f2|seq} | .a + .b'

【讨论】:

    【解决方案2】:

    可以这样做:

    #!/usr/bin/env sh
    
    file1='a.txt'
    file2='b.txt'
    
    array2="$(cat "${file2}")"
    
    for i in $(cat "${file1}"); do
      for j in ${array2}; do
        echo "${i}${j}"
      done
    done
    

    【讨论】:

    • 由于 file1 和 2 只被引用一次,我认为额外的引用没有多大意义。对于array1,也没有理由使用它——cat命令可以正常工作,而对于array2,避免一遍又一遍地读取同一个文件是合理的。除此之外,它是最好、最清晰、最直接的解决方案。 +1。
    • @userunknown 答案已更新为仅在 array2 中为内部循环预取 file2,但在外部循环中读取 file1
    【解决方案3】:

    这可以通过 awk 简单地完成,方法是将每个文件中的值存储在一个数组中,然后使用一组嵌套的 for 循环简单地输出值,例如

    awk '
        FNR == NR {a[i++] = $1}
        FNR < NR {b[j++] = $1}
        END { 
            for (i in a)
                for (j in b)
                    printf "%s%s\n", a[i], b[j] }
    ' file1 file2
    

    该命令通过比较FNR(文件记录号)和NR(记录总数)来工作。如果它们相等,则您正在读取第一个文件,将这些行存储在数组a 中。如果NR &gt; FNR,您正在读取第二个文件,则将行存储在数组b 中。在END 内,只需使用嵌套循环输出数组以获得所需的输出。 (您可以在 END 的开头添加验证,例如 if (i != j) 以验证每个记录的数量相等(如果这是一个条件)

    假设您的两个文件显示为file1file2 将导致以下输出:

    AX
    AY
    AZ
    BX
    BY
    BZ
    CX
    CY
    CZ
    

    (您可以简单地选择awk 命令,然后用鼠标中键将其粘贴到您的终端进行测试,例如)

    $ awk '
    >     FNR == NR {a[i++] = $1}
    >     FNR < NR {b[j++] = $1}
    >     END {
    >         for (i in a)
    >             for (j in b)
    >                 printf "%s%s\n", a[i], b[j] }
    > ' file1 file2
    AX
    AY
    AZ
    BX
    BY
    BZ
    CX
    CY
    CZ
    

    【讨论】:

      【解决方案4】:

      对于大文件,这可能会很慢,但这也有效:

      cat file1.txt | xargs -d ' ' -I var sh -c 'for i in `cat file2.txt`; do echo var$i; done'
      
      AX
      AY
      AZ
      BX
      BY
      BZ
      CX
      CY
      CZ
      

      编辑 通过先将第二个文件的内容写入变量,这可能会更有效

      SECOND_FILE=$(cat file2.txt) | cat file1.txt | xargs -d ' ' -I var sh -c 'for i in `echo $SECOND_FILE`; do echo var$i; done'
      

      如果您想了解此命令和其他命令,我推荐explain shell

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-18
        • 2022-01-05
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多