파일의 두 번째 필드를 밑줄(공백으로 구분)로 분할하고 두 번째 부분을 데이터에 새 필드(탭으로 출력)로 추가하는 방법을 더 간단하게 만들고 싶은 질문이 있습니다.
예를 들어
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
입력 줄이 공백으로 자동 분할되어 $1
m $2
... 이 됩니다 $N
. gsub(/ */,"\t");
모든 공백을 탭으로 바꾸고 ; 까지의 모든 내용을 삭제하고 ( ) 줄을 인쇄한 다음 탭과 수정된 두 번째 필드를 l=$2
인쇄 합니다.l
sub(/.*_/,"",l);
_
l
print $0"\t"l
$0
답변3
t=$(printf \\t)
sed "s/[^ _]*\(_\([^ _]*\)\)\{0,1\}[^ ]*/& \2/2;s/ */$t/g" <in >out
...두 번째 필드의 _ 수에 관계없이 또는 필드 수에 관계없이 작동해야 합니다. 그러나 일련의 공백을 단일 탭 문자로 변환합니다. 두 개의 연속 공백이 두 개의 필드 구분 기호로 간주되어야 하는 경우 다음을 사용하세요.
y/ /$t/
...대신 거기로 가세요...
s/ */$t/
...치환.