連続する行の繰り返し部分を折りたたむ

連続する行の繰り返し部分を折りたたむ

メモ帳に次のようなデータがあります:

4480-1
4480-2
4480-3
4480-15
4581-1
4581-2
4581-3
4581-4

for ループのようなものを使ってこれを行うことはできますか? sed を使用すれば?

私の求める出力は4480-1&-2&-3&-15&4581-1&-2&-3&-4

答え1

これは動作するはずです:

awk -F- '$1!=a{printf "%s", $1} {printf "-%s&", $2} {a=$1}' file | sed 's/&$/\n/g'

アウトアウト:

4480-1&-2&-3&-15&4581-1&-2&-3&-4

説明:

  • awk -F-区切り文字は-
  • $1!=a{printf "%s", $1}4480最後に処理された行と同じでない場合は最初の部分を出力します
  • {printf "-%s&", $2}&最後に2番目の部分を印刷します
  • {a=$1}処理された行にaを設定する
  • sed 's/&$/\n/g'最後の文字を削除し&、改行を追加します。

答え2

簡単にできるとは思えませんsed。 を使用すると簡単になりますperl:

$ perl -F'-' -anle '
    $h{$F[0]} .= defined($h{$F[0]}) ? "&-".$F[1] : "-".$F[1];
    END {
        $,="&";
        print @{[map { $_.$h{$_} } sort { $a <=> $b } keys %h]}
    }
' file
4480-1&-2&-3&-15&4581-1&-2&-3&-4

答え3

おそらく sed では不可能です。私は AWK を使っています。1 行に 1 つのエントリを想定しています。

awk '
  BEGIN { FS="-"; ORS=""; left="" }

  {
    if(NR>1){print "&"}

    # Only print left part if it differs from previous line
    if ($1!=left) {
      print $1 "-" $2
      left=$1;
    } else {
      print "-" $2
    }
  }' inputfile.txt

出力4480-1&-2&-3&-15&4581-1&-2&-3&-4

答え4

sed のはずですが、ここでは perl です:

#!/usr/bin/perl

while ( ($a,$b) = split /-/,<>) { $n->{$a}->{"-$b"}++;}

@_ = map { $_,
           map { chomp; "$_&"; } reverse sort { $a <=> $b } keys $n->{$_};
     } sort { $a <=> $b } keys $n;

@_[-1] =~ s/&$//;

print @_;

入力順序に依存せず、数値順にソートされた出力:

4480-1&-2&-3&-15&4581-1&-2&-3&-4

関連情報