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) 답변을 상당히 직접적으로 번역한 것입니다. -ne
Raku의 비자동 인쇄 "한 줄씩" 명령줄 플래그를 사용하세요. 헤더 줄을 그대로 인쇄하려면 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
답변3
sed를 사용하면 다음과 같은 작업을 수행할 수 있습니다.
sed 's/Total_Soil_[^[:blank:]]*/&_All/' top1.txt
이 작업을 인라인으로 수행하려면 -i
sed 뒤에 추가하세요.
편집하다: 다음을 제외한 모든 항목과 일치 [^ ]
하려면 다음으로 바꾸세요.[^[:blank:]]
공간그리고탭.