真珠

真珠

次のファイルがあります。

Text1 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text1
Text2 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text2
Text3 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text3

「something」、Something、else、およびfooは、任意の文字/スペース/カンマです。これがAAxxxxxxx私が一致させようとしていることです。 X は数値で、常に 0 ~ 9 の 7 つの数字の配列です (例:AA0000001または ) AA9999999AAxxxxxxx列2の部分だけを抽出したいので、出力は次のようになります。

Text1 AAxxxxxxx,AAxxxxxxx text1
Text2 AAxxxxxxx,AAxxxxxxx text2
Text3 AAxxxxxxx,AAxxxxxxx text3

入力例

Text1 somethingAA0123456something,elseAA6543210foo text1
Text2 somethingAA1234567something,elseAA7654321foo text2
Text3 somethingAA2345678something,elseAA8765432foo text3

希望の出力

Text1 AA0123456,AA6543210 text1
Text2 AA1234567,AA7654321 text2
Text3 AA2345678,AA8765432 text3

編集:たとえば、2つ以上の「AAxxxxxxx」セグメントを含む数行があります。

入力する

Text1 somethingAAxxxxxxxsomething,elseAAxxxxxxxfooblahAAxxxxxxx^blahblahAAxxxxxxx text1
Text2 somethingAAxxxxxxxsomething,elseAAxxxxxxxfooblahAAxxxxxxx^blah text2
Text3 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text3

希望の出力

Text1 AA0123456,AA6543210,AA1231252,AA1256712 text1
Text2 AA1234567,AA7654321,AA1926572 text2
Text3 AA2345678,AA8765432 text3

答え1

sedこれは可能です。 4つの一致するグループを使用して、プレフィックス、サフィックス、およびそれらの間の2つのIDを見つけることができます。

パスワード:

sed -rn 's/([^ ]+) .*(AA[0-9]{7}).*(AA[0-9]{7}).* ([^ ]+)/\1 \2,\3 \4/p' file1

テストデータ:

Text1 somethingAA0123456something,elseAA6543210foo text1
Text2 somethingAA1234567something,elseAA7654321foo text2
Text3 somethingAA2345678something,elseAA8765432foo text3

結果:

Text1 AA0123456,AA6543210 text1
Text2 AA1234567,AA7654321 text2
Text3 AA2345678,AA8765432 text3

答え2

perl方法。方法は似ていますsed。長い正規表現に対してこの行をテストして、行の関連する必須部分を $1、$2、$3、$4 としてキャプチャします。 $_に答えを設定し、「-p」フラグを使用して印刷します。

$ perl -pe 'if(/^(Text\d+) .*(AA\d{7}).*(AA\d{7}).* (.*)/){$_="$1 $2,$3 $4$/"}' file1
Text1 AA0123456,AA6543210 text1
Text2 AA1234567,AA7654321 text2
Text3 AA2345678,AA8765432 text3
$

答え3

奇妙な解決策:

$ a="Text1 somethingAA0123456something,elseAA9876543foo text1"
$ awk -F"[ ,]" '{match($2,/(AA[0-9]{7})/,a);match($3,/(AA[0-9]{7})/,b);print $1,a[1],",",b[1],$NF}' <<<"$a"
Text1 AA0123456,AA9876543 text1

これはまた働きます:

$ awk '{match($0,/(\w+\s)(\w+)(\w\w[0-9]{7})(\w+,\w+)(\w\w[0-9]{7})(\w+\s)(\w+)/,a);print a[1],a[3],",",a[5],a[7]}' <<<"$a"

修正する
新しい要件とGNU awkの場合は、次のように使用できます。

$ echo "$b"
Text1 somethingAA1111111something,elseAA2222222fooblahAA3333333^blahblahAA4444444 text1
Text2 somethingAA1111111something,elseAA7777777fooblahAA5454545^blah text2
Text3 somethingAA1111111something,elseAA2222222foo text3

$ awk '{gsub(/(AA[0-9]{7})/," & ",$2)}1' <<<"$b" |awk '{printf("%s ",$1);for (i=2;i<NF;i++) {if($i ~ /AA[0-9]+/) printf("%s%s",$i,(i==NF-1)?" ":",")}}{printf(" %s\n",$NF)}'
Text1 AA1111111,AA2222222,AA3333333,AA4444444  text1
Text2 AA1111111,AA7777777,AA5454545, text2
Text3 AA1111111,AA2222222, text3

唯一の欠陥は、いくつかのレコードの最後のAAXXXXXXXの後に追加のコンマがあることです。これが大きな問題ではないことを願っています。

このソリューションは2つのawksを組み合わせます。まず awk は、AAXXXXXXX各検索の前後にスペースを挿入して各行を変換します。

$ echo "$a"
Text2 somethingAA1234567something,elseAA0987654fooblahAA3333333^blah text2
$ awk '{gsub(/(AA[0-9]{7})/," & ",$2)}1' <<<"$a"
Text2 something AA1234567 something,else AA0987654 fooblah AA3333333 ^blah text2

変換されたレコードは、パターンに一致する最初、最後、および中間フィールドを印刷する2番目のawkに供給されます。AAXXXXXXX

答え4

真珠

perl -pale '$_ = join $", $F[0], join(",", $F[1] =~ /AA\d{7}/g), @F[2..$#F]' yourfile

吹く

ここでの使用は意図的なものです。これは、位置パラメータを中断してサブシェルで実行したくないcatためです。($1, $2, ..., $#)while-loop

cat yourfile |
while read -r f1 f2 rem; do
   set -- "$f1" "$(printf '%s\n' "$f2" | grep -oP 'AA\d{7}' | paste -sd,)" "$rem"
   printf '%s\n' "$*"
done

sed -e '
   s/[^ ]*[ ]*/&\
\
/
   s/AA[0-9]\{7\}/\
&\
/g

   :loop
      s/\nAA[0-9]\{7\}\(\n\)/\1&/
      s/\n\n.*\(\n\n\)/\1/
      s/\(\n\n\)\(AA[0-9]\{7\}\)\n/\2,\1/
   /\nAA[0-9]\{7\}\n/bloop

   s/,\n\n[^ ]*//
' yourfile

関連情報