シェルで数字行とアルファベット行のテキストをマージする方法は?


10

次のようなテキストを持つファイルがあります。

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

等...

そして、アルファベットの行と数値の行を一致させて、次のようにします。

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

誰かがこれを達成する簡単な方法を知っていますか?


emacs.. あなたはelisp解決策を探していますか、またはemacs内からシェルスクリプトを実行する方法を探していますか?
Peter.O 2012年

回答:


3

使用する1つの方法perl

内容script.pl

use warnings;
use strict;

## Check arguments.
die qq[Usage: perl $0 <input-file>\n] unless @ARGV == 1;

my (@alpha, @digit);

while ( <> ) {
        ## Omit blank lines.
        next if m/\A\s*\Z/;

        ## Remove leading and trailing spaces.
        s/\A\s*//;
        s/\s*\Z//;

        ## Save alphanumeric fields and fields with
        ## only digits to different arrays.
        if ( m/\A[[:alpha:]]+\Z/ ) {
                push @alpha, $_;
        }
        elsif ( m/\A[[:digit:]]+\Z/ ) {
                push @digit, $_;
        }
}

## Get same positions from both arrays and print them
## in the same line.
for my $i ( 0 .. $#alpha ) {
        printf qq[%s %s\n], $alpha[ $i ], $digit[ $i ];
}

内容infile

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

次のように実行します。

perl script.pl infile

そして結果:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890

興味深い... 先行スペースと後続スペース削除する 2つの正規表現置換行は、後方参照と非貪欲を使用する単一行よりも約1.6倍速く実行されますs/\A\s*(.*?)\s*\Z/\1/
Peter.O

4

ではawk、ファイルが適切にフォーマットされていると仮定して、空の行を保持しますが、ファイルをチェックするロジックを追加できます。

awk -v RS="" '{for(i=1; i<=NF; i++) a[i]=$i
  getline
  for(i=1; i<=NF; i++) print a[i] " " $i
  print ""}' file

4
<input sed -nr '/^[A-Z]{4}$/,/^$/w out1
                /^[0-9]{4}$/,/^$/w out2'
paste -d' ' out1 out2 |sed 's/^ $//' 

または、一時ファイルなしで、単一のステップで

paste -d' ' <(sed -nr '/^[A-Z]{4}$/,/^$/p' input) \
            <(sed -nr '/^[0-9]{4}$/,/^$/p' input) | sed 's/^ $//' 

最後のsedステップでは、paste... によって導入された空白行の区切り文字を削除します。


3

emacsでは、四角形の操作を使用してテキスト行を切り取り、数値行の前に貼り付けます。


ありがとうございますが、15000以上の回線には適していません。+ 1は有効なアイデアであり、担当者が必要です:)
NWS

2

エントリが正しい場合、

  1. 次を使用して、入力をアルファベット入力と数値入力に分割しますgrep

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. 得られた二つのファイルを結合、alphaおよびdigit、使用してpaste

    • paste alpha digit-d " "タブの代わりにスペースを使用するように追加できます)

1
一時ファイルなし:paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file)または単一のプロセス置換:grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file)
jfg956

1

ひどいawkには、プッシュ/ポップ/シフト解除/シフト機能がありません。これが短いPerlスニペットです

perl -M5.010 -lne '
  given ($_) {
    when (/^[[:alpha:]]+$/) {push @alpha, $_}
    when (/^\d+$/) {say shift(@alpha), " ", $_}
    default {say}
  }
'

実行すると、グループごとに余分な(先頭の)空白行が出力されます。
Peter.O 2012年

default条項により、空白行はすぐに印刷されるため、「1234」の前の空白は「AAAA」行の前に表示されます。
グレン・ジャックマン2012年

0

テキスト付きのファイルを作成し、pr以下のように置換構文を使用して処理してみます。

$ pr -mt <(grep -i "^[a-z]" file.txt) <(grep -i "^[0-9]" file.txt)
AAAA                    1234
BBBB                    5678
CCCC                    9012
DDDD                    3456
EEEE                    7890

で幅を調整し-w9たり、でスペースを削除したりできますsed "s/ //g"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.