【问题标题】:Bash/AWK conditionals using two files使用两个文件的 Bash/AWK 条件
【发布时间】:2021-05-14 21:27:17
【问题描述】:

首先,感谢您的帮助。我在尝试使用两个文件使用 bash 条件时遇到问题。我有文件 letters.txt

A
B
C

我有文件 number.txt

B  10
D  20
A  15
C  18
E  23
A  12
B  14

我想使用条件,所以如果文件 letter.txt 中的一个字母也在 number.txt 中,它会生成文件 a.txt b.txt c.txt 所以看起来像这样:

一个.txt

A  12
A  15

b.txt

 B  10
 B  14

c.txt

C  18

我知道我可以使用此代码:

cat number.txt | awk '{if($1=="A")print $0}' > a.txt

但我想用两个文件来做。

【问题讨论】:

    标签: awk conditional-statements


    【解决方案1】:

    解决此类问题的有效方法是首先对关键字段上的输入进行排序,这样您就不需要同时打开多个输出文件(这有限制和/或可能会减慢处理速度它们)或在读取每一行时打开/关闭输出文件(这总是很慢)。

    -s(稳定排序)使用 GNU 排序来保留非关键字段的输入顺序,并且一次只打开 1 个输出文件,并在整个填充过程中保持打开状态:

    $ sort -k1,1 -s number.txt |
    awk '
        NR==FNR { lets[$1]; next }
        !($1 in lets) { next }
        $1 != prev { close(out); out=tolower($1) ".txt"; prev=$1 }
        { print > out }
    ' letters.txt -
    
    $ head ?.txt
    ==> a.txt <==
    A  15
    A  12
    
    ==> b.txt <==
    B  10
    B  14
    
    ==> c.txt <==
    C  18
    

    如果您没有 GNU sort for -s 来保留每个关键字段的行的输入顺序,您可以将其替换为 awk | sort | cut,例如:

    $ sort -k1,1 -s number.txt
    A  15
    A  12
    B  10
    B  14
    C  18
    D  20
    E  23
    

    $ awk '{print NR, $0}' number.txt | sort -k2,2 -k1,1n | cut -d' ' -f2-
    A  15
    A  12
    B  10
    B  14
    C  18
    D  20
    E  23
    

    请注意A 的第二个字段的顺序与不执行上述操作的输入顺序相比的变化,因为默认情况下sort 不保证保留它排序的每个键的相对行顺序:

    $ sort -k1,1 number.txt
    A  12
    A  15
    B  10
    B  14
    C  18
    D  20
    E  23
    

    【讨论】:

      【解决方案2】:

      使用您展示的示例,请尝试以下操作。

      awk '
      FNR==NR{
        arr[$0]
        next
      }
      ($1 in arr){
        outputFile=(tolower($1)".txt")
        print >> (outputFile)
        close(outputFile)
      }
      ' letters.txt numbers.txt
      

      说明:为上述添加详细说明。

      awk '                      ##Starting awk program from here.
      FNR==NR{                   ##Checking condition which will be TRUE when letters.txt is being read.
        arr[$0]                  ##Creating array arr with index of current line.
        next                     ##next will skip all further statements from here.
      }
      ($1 in arr){               ##checking condition if 1st field is present in arr.
        outputFile=(tolower($1)".txt")    ##Creating outputFile to print output.
        print >> (outputFile)    ##Printing current line into output file.
        close(outputFile)        ##Closing output file in backend.
      }
      ' letters.txt numbers.txt  ##Mentioning Input_file names here.
      

      【讨论】:

        猜你喜欢
        • 2023-03-11
        • 2019-06-14
        • 1970-01-01
        • 1970-01-01
        • 2019-02-20
        • 2018-12-19
        • 2021-10-30
        • 2012-10-26
        • 2017-01-31
        相关资源
        最近更新 更多