이런 파일이 있어요
A1: abc.com B1: Hi there
B1: Your Test mail A1: gml.com
B1: Your new mail A1: hml.com
A1: def.com B1: Test email
B1: hello world A1: yml.com
저는 항상 부품을 먼저 선택한 A1: <string>
다음 B1: <string>
부품을 선택하고 싶습니다.
나는 다음을 시도 grep
하고 좋아했습니다awk
grep -Po '(?<=A1:)\W*\K[^ ]*' file.txt
awk -F"A1:|B1:" '{print $1 $2}' file.txt
하지만 정확한 결과를 내지는 않았습니다
출력이 다음과 같기를 원합니다.
A1: abc.com B1: Hi there
A1: gml.com B1: Your Test mail
A1: hml.com B1: Your new mail
A1: def.com B1: Test email
A1: yml.com B1: hello world
답변1
로 시작하는 줄을 그대로 두고 A1
다음으로 다시 정렬 할 수 있습니다.B1
# if -E or -r is not supported: sed 's/\(B1:.*\)\(A1:.*\)/\2 \1/' ip.txt
$ sed -E 's/(B1:.*)(A1:.*)/\2 \1/' ip.txt
A1: abc.com B1: Hi there
A1: gml.com B1: Your Test mail
A1: hml.com B1: Your new mail
A1: def.com B1: Test email
A1: yml.com B1: hello world
.*
욕심이 많으므로 이 솔루션은 다음과 같이 가정A1:
하고B1:
각 행에서 고유합니다.(B1:.*)(A1:.*)
두 개의 캡처링 그룹이 있습니다. 전체 표현식을 충족하기 위해 첫 번째 캡처링 그룹은B1:
최대 before 까지의 모든 문자열을 캡처합니다A1:
. 두 번째는A1:
줄 끝부터 시작하는 문자열을 캡처 합니다.\2 \1
캡처된 문자열을 사이에 공백을 포함하여 다시 정렬합니다.- 추가 자료:https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions
그리고awk
$ awk -F'A1:' '{print $1 ~ /B1:/ ? FS $2 " " $1 : $0}' ip.txt
A1: abc.com B1: Hi there
A1: gml.com B1: Your Test mail
A1: hml.com B1: Your new mail
A1: def.com B1: Test email
A1: yml.com B1: hello world
첫 번째 필드에 가 포함되어 있으면 B1:
필드를 다시 정렬하고, 그렇지 않으면 입력 줄을 있는 그대로 인쇄합니다.
답변2
다음을 사용하여 이 작업을 수행할 수 있습니다.
perl -F'/(A1:|B1:)/' -lane '
my %h = @F[1..$#F];
print map { "$_$h{$_} " } qw/A1: B1:/;
' input.txt
산출:
A1: gml.com B1: Your Test mail
A1: abc.com B1: Hi there
A1: hml.com B1: Your new mail
A1: def.com B1: Test email
A1: yml.com B1: hello world
설명하다:
- A1: 및/또는 B1:에서 각 레코드를 분할하고 "분할자"도 포함합니다.
- @F 배열의 첫 번째 필드는 무시되어야 합니다. 따라서 @F 배열에는 짝수 개의 요소가 있으며, 이는 "A1:" 및 "B1:" 키를 사용하여 해시 %h로 저장됩니다.
- 이제 지정된 순서로 익명 배열 qw/.../를 반복하고 결과를 stdout에 인쇄합니다.