"sed"를 사용하여 TSV 파일의 필드 끝에 텍스트 삽입

"sed"를 사용하여 TSV 파일의 필드 끝에 텍스트 삽입

sed와일드카드 표현식이 포함된 명령을 사용하여 TSV 파일에 문자를 삽입하고 싶습니다 .

다음과 같은 파일이 있습니다.

Marker  Pvalue  Trait   Chr Pos
S3_16887238 6.172847e-09    Total_Soil_S    3   16887238
S3_16887238 6.172847e-09    Total_Soil_Pa   3   16887238
S3_16887238 6.172847e-09    Total_Soil_Cl   3   16887238

_All세 번째 열의 모든 텍스트 끝에 다음과 같은 내용을 추가하고 싶습니다 .

Marker  Pvalue  Trait   Chr Pos
S3_16887238 6.172847e-09    Total_Soil_S_All    3   16887238
S3_16887238 6.172847e-09    Total_Soil_Pa_All   3   16887238
S3_16887238 6.172847e-09    Total_Soil_Cl_All   3   16887238

이 명령을 사용하고 있지만 작동하지 않습니다.

sed -i 's/Total_Soil_\(.*\)/&_\1_All/g' top1.txt

S이것은 단지 샘플 파일이므로 , Pa및 를 대체할 수 있습니다 Cl.

답변1

sed수정하려는 데이터에서 정확한 위치를 찾기가 어렵기 때문에 표 형식 데이터를 사용하지 않는 것이 좋습니다 . 이 sed유틸리티는 텍스트와 같은 구조화되지 않은 데이터를 처리하는 데 더 적합합니다.


사용밀러( mlr; 구조화된 데이터 작업을 위해 특별히 설계된 도구)는 _All각 TSV 레코드 필드의 데이터 끝에 문자열을 추가합니다.Trait

$ mlr --tsv put '$Trait .= "_All"' file
Marker  Pvalue  Trait   Chr     Pos
S3_16887238     6.172847e-09    Total_Soil_S_All        3       16887238
S3_16887238     6.172847e-09    Total_Soil_Pa_All       3       16887238
S3_16887238     6.172847e-09    Total_Soil_Cl_All       3       16887238

mlr옵션과 함께 사용하여 -I변경 사항을 적용하세요.

Total_Soil필드가 문자열로 시작하는 경우에만 수정되도록 한 다음 다음을 사용해야 합니까?

mlr --tsv put '$Trait =~ "^Total_Soil" { $Trait .= "_All" }' file

다음을 사용하여 각 레코드의 탭으로 구분된 세 번째 필드에 있는 데이터 끝에 awk문자열을 추가합니다 ._All

$ awk -F '\t' 'BEGIN { OFS=FS } NR > 1 { $3 = $3 "_All" }; 1' file
Marker  Pvalue  Trait       Chr     Pos
S3_16887238     6.172847e-09    Total_Soil_S_All        3       16887238
S3_16887238     6.172847e-09    Total_Soil_Pa_All       3       16887238
S3_16887238     6.172847e-09    Total_Soil_Cl_All       3       16887238

1코드 끝을 후행하면 awk수정된 레코드가 무조건 출력됩니다. 어떻게 보면 글쓰기의 축약형이다 { print }. 헤더 수정을 명시적으로 방지해야 한다는 점에 유의하세요. NR > 1테스트가 다음과 같이 평가될 때 필드의 사용 및 수정만 테스트하여 이를 수행합니다 .진짜( NR현재 레코드의 일련번호입니다.)

출력을 새 파일로 리디렉션하고 새 파일의 이름을 원래 이름으로 바꿉니다. 또는 GNU를 사용하는 경우 지침을 따르고 다음을 사용하십시오 awk.-i inplace또 다른 질문 + 답변입니다.

마찬가지로 string으로 시작하는 세 번째 필드만 수정되도록 하려면 Total_Soil다음을 사용하세요.

awk -F '\t' 'BEGIN { OFS=FS } NR > 1 && $3 ~ /^Total_Soil/ { $3 = $3 "_All" }; 1' file

Perl을 사용하는 것은 다음과 거의 동일합니다 awk.

$ perl -F'\t' -e 'BEGIN { $" = "\t" } if ($. > 1) { $F[2] .= "_All" } print "@F"' file
Marker  Pvalue  Trait   Chr     Pos
S3_16887238     6.172847e-09    Total_Soil_S_All        3       16887238
S3_16887238     6.172847e-09    Total_Soil_Pa_All       3       16887238
S3_16887238     6.172847e-09    Total_Soil_Cl_All       3       16887238

Total_Soil데이터 만 수정하는지 확인하세요 .

perl -F'\t' -e 'BEGIN { $" = "\t" } if ($. > 1 && $F[2] =~ /^Total_Soil/) { $F[2] .= "_All" } print "@F"' file

답변2

사용행복하다(이전 Perl_6)

~$ raku -ne 'BEGIN put get; my @a = .split("\t"); @a.[2] = @a.[2] ~ "_All"; put @a.join("\t");' file

Raku는 Perl 프로그래밍 언어 계열의 구성원입니다. Raku의 장점 중 하나는 외부 라이브러리(또는 특수 플래그)가 필요하지 않은 내장 유니코드에 대한 고급 지원입니다.

위의 내용은 @Kusalananda의 우수한 Perl(5) 답변을 상당히 직접적으로 번역한 것입니다. -neRaku의 비자동 인쇄 "한 줄씩" 명령줄 플래그를 사용하세요. 헤더 줄을 그대로 인쇄하려면 BEGIN페이저를 사용하여 put get첫 번째 줄에 넣습니다(인쇄에는 종결자를 사용함) get.

line-by-line 명령의 본문은 다음과 같이 작동합니다. 배열을 선언하고 탭의 입력 행을 my @a해당 배열에 할당합니다.$_.split("\t").split("\t")$_.split("\t")

세 번째 요소(예: 열)를 가져 와서 물결표가 있는 후행 문자열과 연결된 @a.[2]동일한 요소로 덮어씁니다 .@a.[2] ~ "_All"_All

그런 다음 모든 @a요소를 ​​가져와 join탭에서 다시 그룹화하고 출력합니다 put.

입력 예:

Marker  Pvalue  Trait   Chr Pos
S3_16887238 6.172847e-09    Total_Soil_S    3   16887238
S3_16887238 6.172847e-09    Total_Soil_Pa   3   16887238
S3_16887238 6.172847e-09    Total_Soil_Cl   3   16887238

예제 출력:

Marker  Pvalue  Trait   Chr Pos
S3_16887238 6.172847e-09    Total_Soil_S_All    3   16887238
S3_16887238 6.172847e-09    Total_Soil_Pa_All   3   16887238
S3_16887238 6.172847e-09    Total_Soil_Cl_All   3   16887238

https://docs.raku.org
https://raku.org

답변3

sed를 사용하면 다음과 같은 작업을 수행할 수 있습니다.

sed 's/Total_Soil_[^[:blank:]]*/&_All/' top1.txt

이 작업을 인라인으로 수행하려면 -ised 뒤에 추가하세요.

편집하다: 다음을 제외한 모든 항목과 일치 [^ ]하려면 다음으로 바꾸세요.[^[:blank:]]공간그리고.

관련 정보