패턴에 따라 데이터를 재배열

패턴에 따라 데이터를 재배열

이런 파일이 있어요

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에 인쇄합니다.

관련 정보