UNIXコマンドを使用して文字列を新しい行と一重引用符で並べ替える

UNIXコマンドを使用して文字列を新しい行と一重引用符で並べ替える

次のようなテキストがたくさんあります。

K1      CM1     TN1     CT14    D01
K2      CM2     TN2     CT15    D02
K3      CM3     TN3     CT16    D03
K4      CM4     TN4     CT17    D04
K5      CM5     TN5     CT18    D05
K6      CM6     TN6     CT19    D06
K7      CM11    TN7     CT20    D07
K8      CM12    TN8             D08
TW10    CM15    TN9             D09
TW11            TN10            D11
TW12            TN11            D12
TW16            TN12            D6W

(列は空にすることができ、空白ではなくタブで区切ることができます。 - cas)

BBeditのRun Unixコマンド機能を使用して、このテキストを次のように変換したいと思います。

'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'

ご覧のとおり、各文字列は一重引用符で囲まれ、最後の文字列と区別され、その後にカンマが続きます。

よろしくお願いします。

答え1

入力にタブ区切りのフィールドがある行があり、まず上から下に各行の最初のフィールドが必要で、2番目のフィールドなどが必要で、引用符とコンマが必要であると仮定すると、次のような安価なソリューションがあります。

最大9つの列を持つ2つの見苦しい行(sedを使用してフォーマットされています):

for i in 1 2 3 4 5 6 7 8 9; do cut -f$i file.txt; done | 
    grep -v '^$' | sed  -e "s/^/'/" -e "s/\$/'/" -e '$!s/$/,/'

AWKを使用した手動転置(最後のコンマを削除するためにsedを追加):

awk -F'\t' 'NF > cols {cols=NF}
                      {for (i=1; i<=NF; i++) { a[i,NR]=$i }} 
            END { for (j=1;j<=cols;j++) for (i=1;i<=NR;i++)
                      if (a[j, i] != "") printf "\047%s\047,\n", a[j, i] }' file.txt |
    sed -e '$s/,$//'

GNU datamashを使用(およびフォーマット用のsed):

datamash --no-strict transpose < file.txt | tr -s '\t' '\n' |
    sed -e "s/^/'/" -e "s/\$/'/" -e '$!s/$/,/'

(Linuxでテストされており、最初の2つはmacOSでも動作します)

答え2

grepとsedを試すこともできます。

for i in K TW CM TN CT D ;do grep -ow $i[0-9]*[A-Z]* <input_file;done

各項目を一重引用符で囲み、各行の末尾にコンマを追加するには、上記を次のコマンドにパイプします。

sed "s/$/\'\,/" | sed "s/^/\'/"

答え3

これが何を意味するのかわかりませんが、the Run Unix command feature in BBedit表示された入力に基づいて表示される出力を生成するためにUnixコマンドを探している場合は、awkを使用してフィールドがタブで区切られているとします。

$ cat tst.awk
BEGIN { FS="\t" }
{
    for ( i=1; i<=NF; i++ ) {
        if ( $i != "" ) {
            a[i,NR] = $i
            max_j[i] = NR
        }
    }
    max_i = (max_i > NF ? max_i : NF)
}
END {
    for ( i=1; i<=max_i; i++ ) {
        for ( j=1; j<=max_j[i]; j++ ) {
            printf "%s\047%s\047", sep, a[i,j]
            sep = ",\n"
        }
    }
    print ""
}

$ awk -f tst.awk file
'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'

答え4

パールの使用:

$ perl -lne '
    # split each input line on single tabs (not one-or-more
    # whitespace chars) into temporary array @F.
    @F = split /\t/;

    # Construct an Array-of-Arrays (AoA) containing the data.
    # This works with any number of columns, not limited to 5.
    # Assumes each input line has the same number of fields,
    # although some may be empty.
    foreach my $i (keys @F) {
        if (length($F[$i]) > 0) {
          push @{$columns[$i]}, "\047" . $F[$i] ."\047" ;
        };
    };

    END {
        # flatten the AoA with map and print it
        print join(",\n", map { @$_ } @columns);
    }' input.txt 
'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'

@columnsこれは入力を1行ずつ読み、単一のタブ文字を区切り文字として各行を分割し、一重引用符(8進数)で囲まれた各行のnull以外の列から呼び出される配列の配列を構成します\047

ファイル全体を読み取るときは、map「平坦化」(つまり、単一の配列に変換)を使用し、各,\n要素間に印刷します。


ちなみに、mapリスト/配列の操作を実行するための組み込みPerl関数です。珍しい特殊forループだと思います。perldoc -f map詳細より。perldoc -f splitPerlの機能に慣れていない場合でも読んでみるとsplit便利です。しかもperldoc -f join

関連情報