
다음과 같은 파일이 있습니다
'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'
'ABC'|filler|'N'|'mary/2'|'text'
'DEF'|filler|'N'|'jane/3'|'text'
초기 grep 이후,
$ wordY="'Y'|"
$ wordN="'N'|"
$ grep ABC test.txt | grep "$wordY\|$wordN'[[:alpha:]]+/"
돌아오는 중
'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'
'ABC'|filler|'N'|'mary/2'|'text'
/
이제 이름만 제거하고 새 .txt 파일에 저장하고 싶습니다 .
그래서 내 이상적인 출력은
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt' -- / should not be removed for 'te/xt'
'ABC'|filler|'N'|'mary2'|'text'
출력을 얻으려면 명령에 어떻게 추가해야 합니까?
답변1
입력이 |
필드 구분 기호로 사용되는 "간단한" CSV 파일이고 포함된 구분 기호나 줄 바꿈이 있는 필드가 없다고 가정하면 awk
이를 사용하여 수정하려는 특정 필드를 처리할 수 있습니다.
$ awk -F '|' -v sq="'" 'BEGIN { OFS = FS } $1 == sq "ABC" sq { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'
입력을 필드를 구분하는 줄바꿈으로 구분된 레코드 로 읽 -F '|'
습니다 . 인라인 스크립트에서 작은따옴표를 처리하는 것은 까다로울 수 있고 코드를 읽을 수 없게 만들 수 있으므로 변수를 작은따옴표 문자로 설정하기도 합니다.awk
|
awk
awk
sq
코드는 첫 번째 필드의 값이 인 레코드를 감지하고 'ABC'
해당 레코드의 경우 (잠재적으로) 수정된 레코드를 출력하기 전에 네 번째 필드에서 슬래시를 제거합니다.
또한 첫 번째 필드 데이터를 하드코딩하지 않고 감지하려는 전체 문자열을 변수(여기 query
)에 전달할 수도 있습니다.
$ awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'
아래 설명(현재 삭제됨)에 언급된 대로 다음을 수행할 수 있습니다.가능한수정된 레코드의 네 번째 열에 실제로 슬래시가 포함된 경우에만 출력됩니다. 이건 아마단순화하다우리의 명령은 다음과 같습니다:
awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query && gsub("/","",$4)' file
이 gsub()
명령은 대체된 수를 반환합니다. 즉, 원래 네 번째 필드에 있는 슬래시 수를 반환합니다. 그렇지 않은 경우 함수는 0을 반환하고 그 결과 로깅이 발생합니다.아니요인쇄됩니다.
세 번째 필드가 다음과 같은지 확인하시겠습니까? 'Y'
아니면 다음을 'N'
사용할 수 있습니까?
awk -F '|' -v query="'ABC'" -v yn="^'[YN]'$" '
BEGIN { OFS = FS }
$1 == query && $3 ~ yn && gsub("/","",$4)' file
여기서는 세 번째 필드가 변수와 일치해야 하는 정규식을 전달한 awk
다음 yn
이를 사용하여 $3 ~ yn
테스트를 수행합니다. 표현식은 또는 와 ^'[YN]'$
일치합니다 .'Y'
'N'
답변2
사용sed
$ sed -En "\~^('ABC[^YN]*(Y|N)'\|'[[:alpha:]]+)/~s//\1/p" input_file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'
답변3
다음을 수행할 수 있습니다.
$ awk 'BEGIN{FS=OFS="|"; q="\047"}
($1==q"ABC"q)&&($3~q"Y|N"q)&&($4~"/") { sub("/","",$4);print }
' test.txt
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'
필드 구분 기호와 출력 필드 구분 기호를 동일한 값( )으로 설정합니다 |
. 그런 다음 따옴표 문자를 사용하여 변수를 생성하고 q="047"
(이렇게 하면 스크립트의 나머지 부분이 단순화됨) 다음 3가지를 테스트합니다.
- 첫 번째 필드는 와 정확히 같습니다
'ABC'
. - 세 번째 필드는
'Y'
또는 입니다'N'
. - 네 번째 필드에는 실제로
/
.
그런 다음 다음을 수행하십시오.
/
네 번째 필드의 첫 번째 필드를 삭제합니다.- 전체 줄을 인쇄합니다.
이는 정규식을 사용하여 grep Test ABC에 게시한 grep 명령과 다릅니다. 그것이 당신이 원하는 것이라면, 또는 그냥으로 $1 == q"ABC"q
바꾸 십시오 (이렇게 하면 입력 라인 전체에서 ABC를 찾을 수 있습니다).$1 ~ "ABC"
~"ABC"
이러한 값 중 하나에 대한 모든 입력 라인을 테스트하는 것도 Y
중복되는 것 같습니다. N
그렇다면 두 번째 테스트를 삭제할 수 있습니다.
이는 awk 명령을 다음과 같이 단순화합니다.
awk '($1~/ABC/)&&sub("/","",$4)' FS="|" OFS="|" test.txt
네 번째 필드의 모든 항목을 교체해야 하는 경우 /
변경 기능을 사용할 수 있습니다. 일부 운영 체제(현재 운영 체제 포함)에서는sub
gsub
이전 awk
구현gsub를 지원하지 않을 수 있습니다.
답변4
tr
다음과 같은 콘텐츠의 경우:
grep ABC test.txt | grep "$wordY|$wordN'[[:alpha:]]+/" | tr -d '/'
tr
는 "번역"의 약어이며 특정 세트에 나타나는 문자를 제거하거나 다른 세트의 동일한 위치에 있는 문자로 대체하여 변경할 수 있습니다.
이 -d
매개변수는 "문자 제거" 모드를 선택합니다. 여기서는 지정된 세트(여기서 세트는 하나의 문자 "/"임)의 문자가 출력에 다시 쓰여지기 전에 입력에서 제거됩니다.
자세한 내용은 을 참조하십시오 man tr
.