テキストファイルの列を並べ替える方法

テキストファイルの列を並べ替える方法

Linuxでbashを使用して出力内の列がソートされるように、特定の列の前にスペースを挿入するようにテキストファイルを処理するにはどうすればよいですか?たとえば、

入力する

1653455 ASDFASDF22 bla bla bla asd xmv ASDFASDF22 AA
1944444 ASDFASDF22 klasdfmxvl yxklc erisa ask xdk asdm ase ASDFASDF22 BB
1984945 ASDFASDF22 jklyck aklsdfl asfjasl asdkkcii wdkkkxd aslasl wqe ASDFASDF22 BB

出力

1653455 ASDFASDF22 bla bla bla asd xmv                                ASDFASDF22 AA
1944444 ASDFASDF22 klasdfmxvl yxklc erisa ask xdk asdm ase            ASDFASDF22 BB
1984945 ASDFASDF22 jklyck aklsdfl asfjasl asdkkcii wdkkkxd aslasl wqe ASDFASDF22 BB

2つのASDFASDF22sの間の列は50文字未満でなければならず、それ以外の場合は切り捨てる必要があります。

答え1

1つの解決策は以下を使用しますperl

コンテンツscript.pl:

use warnings;
use strict;

## Acept one argumnet, the input file.
@ARGV == 1 or die qq[Usage: perl $0 input-file\n];

while ( <> ) {
        ## Remove last '\n' char.
        chomp;

        ## Split line with string 'ASDFASDF22'
        my @f = split /(ASDFASDF22)/;

        ## Print line but print first 49 chars plus a space of the special string.
        printf qq[%s%-50s%s\n],
                join( qq[], @f[0,1] ),
                substr( $f[2], 0, 49 ) . qq[ ],
                join( qq[], @f[3..$#f] );
}

スクリプトを実行します。

perl script.pl infile

そして出力:

1653455 ASDFASDF22 bla bla bla asd xmv                              ASDFASDF22 AA
1944444 ASDFASDF22 klasdfmxvl yxklc erisa ask xdk asdm ase          ASDFASDF22 BB
1984945 ASDFASDF22 jklyck aklsdfl asfjasl asdkkcii wdkkkxd aslasl w ASDFASDF22 BB

答え2

Bashを使用した配列

while read -r -a words; do
    prefix="${words[0]} ${words[1]}"
    idx=${#words[*]}
    suffix="${words[$((idx-2))]} ${words[$((idx-1))]}"
    unset words[0] words[1] words[$((idx-2))] words[$((idx-1))]
    middle="${words[*]}"
    printf "%s %-50s %s\n" "$prefix" "${middle:0:50}" "$suffix"
done < filename

答え3

劣化が必要なテキストファイルで@Bireiのスクリプトを試みましたが、ファイルに指定された区切り文字と一致しない行がいくつか含まれており、失敗しました(そして劣化は不要です)。したがって、Perlの知識は限られているので、不一致行の処理を避けるために、配列サイズの簡単なチェックを追加しました。他の人がこの変更が必要な場合に備えて、ここに基本コードを投稿します。

use warnings;
use strict;

## Acept one argumnet, the input file.
@ARGV == 1 or die qq[Usage: perl $0 input-file\n];

while ( <> ) {
    ## Remove last '\n' char.
    chomp;

    ## Split line with string 'ASDFASDF22'
    my @f = split /(ASDFASDF22)/;

    my $f = @f;
    # check array size to avoid errors on non-matching lines
    if ($f > 1)
    {
        ## Print line but print first 49 chars plus a space of the special string.
        printf qq[%s%-50s%s\n],
                join( qq[], @f[0,1] ),
                substr( $f[2], 0, 49 ) . qq[ ],
                join( qq[], @f[3..$#f] );

   }
   else
   {
       # output non-matching line as-is
       print $_ . qq[\n];
   }
}

出力例:

1653455 ASDFASDF22 bla bla bla asd xmv                              ASDFASDF22 AA
1944444 ASDFASDF22 klasdfmxvl yxklc erisa ask xdk asdm ase          ASDFASDF22 BB
######################### non-matching line left alone ##########################
1984945 ASDFASDF22 jklyck aklsdfl asfjasl asdkkcii wdkkkxd aslasl w ASDFASDF22 BB

答え4

GNU awk:

awk -F "[[:space:]]+ASDFASDF22[[:space:]]+" \
    'BEGIN { OFS=" ASDFASDF22 "; }
    { 
        $2 = sprintf("%-50s", substr($2, 0, 50));
        print;
    }'

関連情報