파일을 문자별로 분할하여 데이터에 추가합니다.

파일을 문자별로 분할하여 데이터에 추가합니다.

파일의 두 번째 필드를 밑줄(공백으로 구분)로 분할하고 두 번째 부분을 데이터에 새 필드(탭으로 출력)로 추가하는 방법을 더 간단하게 만들고 싶은 질문이 있습니다.

예를 들어 file.txt

2 1_123
2 2_345

out.tab:

2 1_123 123
2 2_345 345

이미 사용할 수 있지만 더 쉬운 방법이 있나요? 너무 복잡해 보이는데...

paste -d' ' file.txt <(cat file.txt | cut -d'_' -f 2- ) | tr [:blank:] \\t > out.temp && mv out.temp out.tab

답변1

모든 변환은 파일의 동일한 줄 내에서 데이터를 섞기 때문에 sed 또는 awk와 같이 데이터를 한 줄씩 조작하는 도구를 사용하는 것이 훨씬 간단합니다.

sed -e 's/^[^ \t]*[ \t][^ \t]*_\([^_ \t]*\)/&\1\t/' -e 'y/ /\t/' <<<'2 1_123'

설명: 정규식을 사용하여 첫 번째 필드(첫 번째 공백 또는 탭까지), 두 번째 필드에서 마지막 밑줄까지, 두 번째 필드는 마지막 밑줄( \(…\)텍스트를 바꾸는 데 사용되도록 그룹에 넣음)과 일치시킵니다. 동일한 텍스트( &대체)를 유지하고 그 뒤에 일치하는 그룹의 내용( \1)이 옵니다. 두 번째 필드 이후의 모든 필드는 변경되지 않습니다. 마지막으로 모든 공백을 탭 문자로 바꿉니다.

sed가 탭 표시를 지원하지 않으면 \t대신 리터럴 탭을 사용하십시오.

답변2

두 번째 및 마지막 필드에 하나의 밑줄만 표시하는 간단한 예를 보려면 다음을 수행할 수 있습니다.

$ sed 's/_\(.*\)/& \1/' file | tr ' ' '\t'
2   1_123   123
2   2_345   345

또는 sed구현이 확장 정규식을 지원하는 경우:

$ sed -E 's/_(.*)/& \1/' file | tr ' ' '\t'
2   1_123   123
2   2_345   345

이것은 첫 번째 항목 _과 그 이후의 모든 항목과 일치합니다. 대괄호는 일치하는 문자열을 캡처하며, 이를 교체 오른쪽에 인용할 수 있습니다 \1. &일치하는 모든 항목이므로 _두 번째 필드의 나머지 부분이 그 뒤에 옵니다. 따라서 교체는 자체, 공백 및 다음 문자를 인쇄합니다 _. tr모든 공백을 탭으로 바꾸십시오.


원하는 수의 필드를 가질 수 있고 그 중 하나를 포함할 수 있는 더 복잡한 경우에는 다음을 _사용할 수 있습니다 perl.

$ perl -lane 's/ +/\t/g; $F[1]=~/_(\S+)/; print "$_\t$1"' file 
2   1_123   123
2   2_345   345

-a이로 인해 perl입력 공간이 배열로 분할 됩니다 @F. 두 번째 필드는 $F[1]배열이 처음부터 계산되기 때문입니다 0. -n"입력 파일을 한 줄씩 읽고 -e주어진 스크립트를 적용" 한다는 의미입니다 . -l입력 줄에서 후행 줄 바꿈을 제거하고 각 호출에 줄 바꿈을 추가합니다 print.

s/ +/\t/g;하나 이상의 공백이 있는 모든 항목을 탭으로 바꾸고 $F[1]=~/_(\S+)/;두 번째 필드의 다음 문자 _와 일치하여 다른 이름으로 저장한 $1다음 print "$_\t$1"현재 줄( $_)과 일치 항목을 인쇄합니다.


현장 데이터를 기반으로 한 또 다른 유용한 도구는 다음과 같습니다 awk.

$ awk '{gsub(/ /,"\t");l=$2; sub(/.*_/,"",l); print $0"\t"l}' file 
2   1_123   123
2   2_345   345

에서는 awk입력 줄이 공백으로 자동 분할되어 $1m $2... 이 됩니다 $N. gsub(/ */,"\t");모든 공백을 탭으로 바꾸고 ; 까지의 모든 내용을 삭제하고 ( ) 줄을 인쇄한 다음 탭과 수정된 두 번째 필드를 l=$2인쇄 합니다.lsub(/.*_/,"",l);_lprint $0"\t"l$0

답변3

t=$(printf \\t)
sed "s/[^ _]*\(_\([^ _]*\)\)\{0,1\}[^ ]*/& \2/2;s/  */$t/g" <in >out

...두 번째 필드의 _ 수에 관계없이 또는 필드 수에 관계없이 작동해야 합니다. 그러나 일련의 공백을 단일 탭 문자로 변환합니다. 두 개의 연속 공백이 두 개의 필드 구분 기호로 간주되어야 하는 경우 다음을 사용하세요.

y/ /$t/

...대신 거기로 가세요...

s/  */$t/

...치환.

관련 정보