首页 文章

如何使用sed / awk切换/旋转每两行?

提问于
浏览
12

我一直在手工做这个,我不能再做了 - 我有几千行,我认为这是sed或awk的工作 .

基本上,我们有一个这样的文件:

A sentence X
A matching sentence Y
A sentence Z
A matching sentence N

此模式将继续整个文件 . 我想翻转每个句子和匹配句子,这样整个文件最终会像:

A matching sentence Y
A sentence X
A matching sentence N
A sentence Z

有小费吗?

编辑:扩展初始问题

Dimitre Radoulov为最初的问题提供了一个很好的答案 . 这是主要问题的延伸 - 更多细节:

假设我们有一个有组织的文件(由于Dimitre提供的sed行,文件是有组织的) . 但是,现在我想按字母顺序组织文件,但只使用第二行的语言(英语) .

watashi 
me
annyonghaseyo
hello
dobroye utro!
Good morning!

我想按英文句子(每第2句)按字母顺序排列 . 鉴于以上输入,这应该是输出:

dobroye utro!
Good morning!
annyonghaseyo
hello
watashi
me

4 回答

  • 1
    sed 'N; 
    s/\(.*\)\n\(.*\)/\2\
    \1/' infile
    

    N - 将下一行输入附加到模式空间中
    \(.*\)\n\(.*\) - 将图案空间的匹配部分保存在换行符之前和之后 .
    \2\\ \1 - 交换两行(\ 1是第一个保存的部分,\ 2是第二个) . 使用转义的文字换行符来实现可移植性

    对于某些sed实现,您可以使用转义序列\ n: \2\n\1 .

  • 9

    对于问题的第一部分,这里是一种在sed中互相交换每一行而不使用正则表达式的方法:

    sed -n 'h;n;p;g;p'
    

    -n 命令行禁止自动打印 . 命令 h 将当前行从模式空间复制到保留空间, n 在模式空间的下一行读取, p 打印它; g 将第一行从保留空间复制回模式空间,将第一行复制回模式空间,然后 p 将其打印出来 .

  • 5

    第一个问题:

    awk '{x = $0; getline; print; print x}' filename
    

    下一个问题:按第二行排序

    paste - - < filename | sort -f -t $'\t' -k 2 | tr '\t' '\n'
    

    哪个输出:

    dobroye utro!
    Good morning!
    annyonghaseyo
    hello
    watashi
    me
    
  • 16

    假设输入文件如下:

    A sentence X
    Z matching sentence Y
    A sentence Z
    B matching sentence N
    A sentence Z
    M matching sentence N
    

    您可以使用Perl进行交换和排序:

    perl -lne'
     $_{ $_ } = $v unless $. % 2;
     $v = $_;
     END {
      print $_, $/, $_{ $_ }
        for sort keys %_; 
       }' infile
    

    我得到的输出是:

    % perl -lne'
     $_{ $_ } = $v unless $. % 2;
     $v = $_;
     END {
      print $_, $/, $_{ $_ }
        for sort keys %_;
       }' infile
    B matching sentence N
    A sentence Z
    M matching sentence N
    A sentence Z
    Z matching sentence Y
    A sentence X
    

    如果您想通过第一行(交换前)订购:

    perl -lne'
     $_{ $_ } = $v unless $. % 2;
     $v = $_;
     END {
      print $_, $/, $_{ $_ }
        for sort {
          $_{ $a } cmp $_{ $b }
          } keys %_; 
       }' infile
    

    所以,如果原始文件看起来像这样:

    % cat infile1
    me
    watashi 
    hello
    annyonghaseyo
    Good morning!
    dobroye utro!
    

    输出应如下所示:

    % perl -lne'
     $_{ $_ } = $v unless $. % 2;
     $v = $_;
     END {
      print $_, $/, $_{ $_ }
        for sort {
      $_{ $a } cmp $_{ $b }
      } keys %_;
       }' infile1
    dobroye utro!
    Good morning!
    annyonghaseyo
    hello
    watashi 
    me
    

    此版本应正确处理重复记录:

    perl -lne'
     $_{ $_, $. } = $v unless $. % 2;
     $v = $_;
     END {
        print substr( $_, 0, length() - 1) , $/, $_{ $_ }
        for sort {
          $_{ $a } cmp $_{ $b }
          } keys %_; 
       }' infile
    

    另一个版本受Glenn发布的解决方案的启发(包括记录交换并假设模式_ZZ_不在文本文件中):

    sed 'N; 
      s/\(.*\)\n\(.*\)/\1_ZZ_\2/' infile | 
        sort |
          sed 's/\(.*\)_ZZ_\(.*\)/\2\
    \1/'
    

相关问题