【问题标题】:How do I split up a line and rearrange its elements?如何拆分一条线并重新排列其元素?
【发布时间】:2010-12-09 08:18:26
【问题描述】:

我在一行中有一些数据,如下所示

abc edf xyz rfg yeg udh

我想将数据呈现如下

abc
xyz
yeg


edf
rfg
udh

以便替代字段以换行符分隔打印。 有没有一种衬里?

【问题讨论】:

    标签: perl unix shell sed awk


    【解决方案1】:

    下面的awk脚本可以做到:

    > echo 'abc edf xyz rfg yeg udh' | awk '{
        for (i = 1;i<=NF;i+=2){print $i}
        print "";
        for (i = 2;i<=NF;i+=2){print $i}
        }'
    abc
    xyz
    yeg
    
    edf
    rfg
    udh
    

    【讨论】:

    • 请完整查看我的问题“替代字段以换行符分隔”
    • 不耐烦的小东西,不是吗? :-) 既然答案是正确的,我假设您将撤销该否决票。
    【解决方案2】:

    Python 本着与上述 awk 相同的精神(4 行):

    $ echo 'abc edf xyz rfg yeg udh' | python -c 'f=raw_input().split()
    > for x in f[::2]: print x
    > print
    > for x in f[1::2]: print x'
    

    Python 1-liner(省略了相同的管道):

    $ python -c 'f=raw_input().split(); print "\n".join(f[::2] + [""] + f[1::2])'
    

    【讨论】:

    • “另一个答案已发布”没有出现。很高兴知道我不是唯一一个有这个想法的人。 Python 有更好的数组切片语法。这是(恕我直言)Perl(那个和字符串索引)中最烦人的遗漏之一。
    【解决方案3】:

    另一个 Perl 5 版本:

    #!/usr/bin/env perl
    use Modern::Perl;
    use List::MoreUtils qw(part);
    
    my $line = 'abc edf xyz rfg yeg udh';
    
    my @fields = split /\s+/, $line; # split on whitespace
    
    # Divide into odd and even-indexed elements
    my $i = 0;
    my ($first, $second) = part { $i++ % 2 }  @fields;
    
    # print them out
    say for @$first;
    say '';          # Newline
    say for @$second;
    

    【讨论】:

    • 我从来没有注意到part,但这正是我想在这里做的事情(grep,但保留通过和失败,每个都在自己返回的数组中) .谢谢。
    【解决方案4】:

    可惜之前的 perl 答案太长了。这里有两个 perl 单行代码:

    echo 'abc edf xyz rfg yeg udh'|
      perl -naE '++$i%2 and say for @F; ++$j%2 and say for "",@F'
    

    在旧版本的 perl 上(没有“say”),你可以使用这个:

    echo 'abc edf xyz rfg yeg udh'|
      perl -nae 'push @{$a[++$i%2]},"$_\n" for "",@F; print map{@$_}@a;'
    

    【讨论】:

      【解决方案5】:

      只是为了比较,这里有一些 Perl 脚本可以做到这一点(毕竟是 TMTOWTDI)。一种相当实用的风格:

      #!/usr/bin/perl -p
      
      use strict;
      use warnings;
      
      my @a = split;
      my @i = map { $_ * 2 } 0 .. $#a / 2;
      print join("\n", @a[@i]), "\n\n",
            join("\n", @a[map { $_ + 1 } @i]), "\n";
      

      我们也可以更接近 AWK 脚本:

      #!/usr/bin/perl -p
      
      use strict;
      use warnings;
      
      my @a = split;
      my @i = map { $_ * 2 } 0 .. $#a / 2;
      print "$a[$_]\n" for @i;
      print "\n";
      print "$a[$_+1]\n" for @i;
      

      我已经没有办法做到这一点,所以如果任何其他聪明的 Perlers 想出了另一种方法,请随时添加它。

      【讨论】:

        【解决方案6】:

        另一个 Perl 解决方案:

        use strict;
        use warnings;
        
        while (<>)
        {
            my @a = split;
            my @b = map { $a[2 * ($_%(@a/2)) + int($_ / (@a /2))]  . "\n" } (0 .. @a-1); 
            print join("\n", @a[0..((@b/2)-1)], '', @a[(@b/2)..@b-1], '');
        }
        

        你甚至可以把它浓缩成一个真正的单行:

        perl -nwle'my @a = split;my @b = map { $a[2 * ($_%(@a/2)) + int($_ / (@a /2))]  . "\n" } (0 .. @a-1);print join("\n", @a[0..((@b/2)-1)], "", @a[(@b/2)..@b-1], "");'
        

        【讨论】:

          【解决方案7】:

          这是过于字面化、不可扩展、超短的awk 版本:

          awk '{printf "%s\n%s\n%s\n\n%s\n%s\n%s\n",$1,$3,$5,$2,$4,$6}'
          

          略长(多两个字符),使用嵌套循环(在末尾打印一个额外的换行符):

          awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;print ""}}'
          

          不打印额外的换行符:

          awk '{for(i=1;i<=2;i++){for(j=i;j<=NF;j+=2)print $j;if(i==1)print ""}}'
          

          作为比较,paxdiablo 的版本删除了所有不必要的字符(1、9 或 11 个字符):

          awk '{for(i=1;i<=NF;i+=2)print $i;print "";for(i=2;i<=NF;i+=2)print $i}'
          

          这是一个全 Bash 版本:

          d=(abc edf xyz rfg yeg udh)
          i="0 2 4 1 3 5"
          for w in $i
          do
              echo ${d[$w]}
              [[ $w == 4 ]]&&echo
          done
          

          【讨论】:

            【解决方案8】:

            我在 haskell 中的尝试:

            Prelude> (\(x,y) -> putStr $ unlines $ map snd (x ++ [(True, "")] ++ y)) $ List.partition fst $ zip (cycle [True, False]) (words "abc edf xyz rfg yeg udh")
            abc
            xyz
            yeg
            
            edf
            rfg
            udh
            Prelude>
            

            【讨论】:

              【解决方案9】:

              你也可以只使用 tr: echo "abc edf xyz rfg yeg udh" | tr ' ' '\n'

              【讨论】:

              • 这只是用换行符替换空格;在单独的行上按顺序打印字段——这不是发帖人想要的。
              【解决方案10】:

              用于比较的 Ruby 版本:

              ARGF.each do |line|
                groups = line.split
                0.step(groups.length-1, 2) { |x| puts groups[x] }
                puts
                1.step(groups.length-1, 2) { |x| puts groups[x] }
              end
              
              ARGF.each do |line|
                groups = line.split
                puts groups.select { |x| groups.index(x) % 2 == 0 }
                puts
                puts groups.select { |x| groups.index(x) % 2 != 0 }
              end
              

              【讨论】:

                【解决方案11】:
                $ echo 'abc edf xyz rfg yeg udh' |awk -vRS=" " 'NR%2;NR%2==0{_[++d]=$0}END{for(i=1;i<=d;i++)print _[i]}'
                abc
                xyz
                yeg
                edf
                rfg
                udh
                

                对于换行符,我留给你自己做。

                【讨论】:

                  【解决方案12】:

                  这里还有另一种方法,使用 Bash 手动重新排列一行中的单词 - 之前转换为数组:

                  echo 'abc edf xyz rfg yeg udh' | while read tline; do twrds=($(echo $tline)); echo -e "${twrd[0]} \n${twrd[2]} \n${twrd[4]} \n\n ${twrd[1]} \n${twrd[3]} \n${twrd[5]} \n" ; done 
                  

                  干杯!

                  【讨论】:

                  • 这限制在一行中只有 5 个单词,如果单词数量增加。这将不起作用。我只是展示了一个示例,但并不总是相同。
                  • 最初的问题表述没有说明“字数”增加的任何内容。干杯!
                  猜你喜欢
                  • 2020-11-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-08-30
                  • 2020-11-13
                  • 1970-01-01
                  • 2016-11-07
                  • 1970-01-01
                  相关资源
                  最近更新 更多