다음과 같은 파일이 있습니다.
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개의 일치하는 그룹을 사용하여 접두사, 접미사 및 그 사이의 두 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 뒤에 추가 쉼표가 있다는 것입니다. 이것이 큰 문제가 아니길 바랍니다.
이 솔루션은 두 개의 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
그런 다음 변환된 레코드는 패턴과 일치하는 첫 번째, 마지막 및 중간 필드를 인쇄하는 두 번째 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