次のファイルがあります。
Text1 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text1
Text2 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text2
Text3 somethingAAxxxxxxxsomething,elseAAxxxxxxxfoo text3
「something」、Something、else、およびfooは、任意の文字/スペース/カンマです。これがAAxxxxxxx
私が一致させようとしていることです。 X は数値で、常に 0 ~ 9 の 7 つの数字の配列です (例:AA0000001
または ) AA9999999
。AAxxxxxxx
列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