【问题标题】:Print two lines at the same time同时打印两行
【发布时间】:2014-02-14 05:44:18
【问题描述】:

我有这个问题,我需要为同一个文件同时打印2行,问题是它必须在第一列的行更改之后发生,例如:

文件:abcd.csv

a,1
a,2
a,3
a,4
a,5
a,6
b,1
b,2
b,3
b,4
b,5
b,6
c,1
c,2
c,3
c,4
c,5
c,6

代码:

awk '{ if ( $1 == "a") print $1,$2 } ' FS="," abcd.csv

哪个打印:

a 1
a 2
a 3
a 4
a 5
a 6

但我同时需要两行,因为我需要将这两行传递给另一个调用:

第一个输出(然后它们将被发送):

a 1
a 2

第二个输出(然后它们将被发送):

a 2
a 3

第三个输出(然后它们将被发送):

a 3
a 4

第四个输出(然后它们将被发送):

a 4
a 5

第 5 个输出(然后它们将被发送):

a 5
a 6

第一列中的其他字母依此类推。

我会很感激这方面的任何提示,

【问题讨论】:

  • 这个必须在awk吗?
  • 您需要将每条过渡线加倍吗?当第二个字段在两行之间没有变化时会发生什么a 1a 2a 2a 3
  • 所以你想每次调用你的awk,你有两行,第一行1,2,然后3,4 ...也就是说,如果你调用100次,你解析文件100 次...我建议您使用 grep/awk... 来获取您需要的所有行,然后使用循环处理那个较小的集合。
  • @Gery 即使您的文件只有 4 行,这也是最糟糕的工作方式。并不容易,你仍然需要循环,你仍然需要将变量传递给 awk 让它知道哪一轮。如果你知道你走错了路,而且没有节省精力,但你继续前进……我只能说“祝你好运”
  • 您的附加电话是什么样的?你说你必须将结果传递给另一个调用。如果您告诉我们更多有关您的设置的信息,也许所有事情都可以通过一个 awk 脚本完成。

标签: linux bash shell awk sh


【解决方案1】:

你需要在你的 awk 调用之后管理这个:

awk -F, '$1 == "a" {print $1,$2}' abcd.csv | 
while read line1; do
    read line2
    printf "%s\n%s\n" "$line1" "$line2" | additional_call
done

【讨论】:

    【解决方案2】:

    我会在无限循环中使用getline() 函数,并在第一个字段与a 字符不同时将其中断:

    awk '
        FNR == 1 {
            while (1) {
                prev_line = $0
                r = getline
                if (r != 1) {
                    exit r
                }
                split(prev_line, arr_prev, /,/)
                split($0, arr, /,/)
                if (arr_prev[1] == "a" && arr[1] == "a") {
                    printf "%s\n%s\n", prev_line, $0
                }
                else {
                    exit 0
                }
                print "============="
            }
        }
    ' infile
    

    它产生:

    a,1 
    a,2 
    ============= 
    a,2 
    a,3 
    ============= 
    a,3 
    a,4 
    ============= 
    a,4 
    a,5 
    ============= 
    a,5 
    a,6 
    =============
    

    更新:为了避免无限循环,我在getline() 结果中添加了一个检查,以在文件结尾或错误中退出。

    【讨论】:

    • 此解决方案在某些情况下会产生真正的无限循环。如果您正在考虑使用 getline,请确保您阅读了 awk.info/?tip/getline 并完全理解所有含义和注意事项。对于 getline 解决方案,这似乎不是一个合适的问题。
    • 我不明白 - 你完全绕过 awks 自然处理循环并添加你自己的。我不明白您为什么要这样做,如果您要这样做,那么为什么要在文件的第一行而不是在 BEGIN 部​​分中这样做,然后为什么要编写一个带有 a 的 while(1) 循环打破而不是给循环一个真实的条件?所有的修辞......只是我有些挠头!
    • @EdMorton:是的。你说的对。这是我的第一个计划,也许我没有深入考虑,但是,嘿,它似乎奏效了!幸运的是,OP 有许多其他解决方案可供选择,比这个设计更好。
    【解决方案3】:

    从您的问题中不清楚您所说的“同时两行”是什么意思,但下面的代码将在每个字母内的两个行组中输出:

    #!/usr/bin/awk -f
    
    BEGIN { FS=","; OFS=","}
    {
        count[$1]++;
        rows[$1][count[$1]] = $2;
    }
    END {
        for(i in count) {
            for(k=1; k<=count[i]-1; k++) {
                print i,rows[i][k]
                print i,rows[i][k+1] 
                print ""
            }
            print ""
                print ""
            }
        }
    

    此代码将输入和输出字段分隔符设置为逗号。然后它创建一个 2D 散列,其中第一个字母和该字母组中的行作为键,第二列作为值。

    最后,它通过每个初始字母的 2D 散列和在该字母集中以两个为一组打印的组行值。

    基于给定输入的输出:

    a,1
    a,2
    
    a,2
    a,3
    
    a,3
    a,4
    
    a,4
    a,5
    
    a,5
    a,6
    
    
    
    b,1
    b,2
    
    b,2
    b,3
    
    b,3
    b,4
    
    b,4
    b,5
    
    b,5
    b,6
    
    
    
    c,1
    c,2
    
    c,2
    c,3
    
    c,3
    c,4
    
    c,4
    c,5
    
    c,5
    c,6
    

    【讨论】:

      【解决方案4】:

      如果您不需要使用awk,那么一个简单的python 程序就足够了:

      #!/usr/bin/python
      
      import sys
      
      with open(sys.argv[1], 'r') as f:
          content = f.readlines()
      
      for i in range(len(content)-1):
          if content[i].split(',')[0] == content[i+1].split(',')[0]:
              print content[i]
              print content[i+1]
      

      【讨论】:

        【解决方案5】:

        您说您需要对每两行进行管道传输以便进行其他调用,如果您一次生成所有输出,那么您仍然需要拆分每对行才能进行其他调用。

        我会在 bash 中执行以下操作,

            FILE=abcd.csv; \
            LINES=`wc -l $FILE | cut -d' ' -f1`; \
            for N in `seq 2 ${LINES}`; do \
                head -n${N} $FILE | tail -n2 | awk '{print $1,$2}' FS="," | cat;  \
            done
        

        done 之前的最后一个| cat 替换为您实际要拨打的电话,这将收到每一对线路。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多