4개의 값(탭으로 구분된 값)이 포함된 .tsv 파일이 있습니다. 따라서 행당 세 개의 탭만 있어야 하며 각 탭 주위에는 다음과 같은 텍스트가 있어야 합니다.
value value2 value3 value4
그런데 일부 행이 깨진 것 같습니다(탭이 3개 이상 있음). 이 줄을 찾아야 해요.
나는 다음 grep 패턴을 생각해 냈습니다.
grep -v "^[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+$"
내 생각:
- 첫 번째 ^는 시작 부분과 일치합니다.
- [^\t]+는 여러 "탭 없음"과 일치합니다.
- \t는 단일 탭 문자와 일치합니다.
- $ 경기 종료
그런 다음 올바른 순서로 올바른 횟수만큼 넣습니다. 이는 올바른 줄과 일치해야 합니다. 그래서 -v 옵션을 통해 복원하여 잘못된 줄을 얻었습니다.
그러나 -v 옵션을 사용하면 파일의 모든 줄과 탭 없이 시도한 임의의 텍스트와 일치합니다.
내 실수가 무엇입니까?
편집: 저는 데비안과 bash를 사용하고 있습니다.
답변1
보시다시피 \t
기본 정규식에는 특별한 것이 없으며 grep
기본적으로 BRE가 사용됩니다. grep
Linux에서 기본적으로 -P
Perl 호환 정규 표현식이 있는 GNU를 사용하면 \t
탭 문자를 사용할 수 있습니다.
그러나 원하는 것을 달성하는 것이 훨씬 쉽습니다 awk
. 입력 필드 구분 기호를 탭( -F '\t'
)으로 설정하고 NF
필드 수( )가 3이 아닌 행을 인쇄하면 됩니다.
awk -F'\t' 'NF!=3' file
file
그러면 3개보다 많거나 적은 필드를 포함하는 모든 줄이 인쇄됩니다 . 3개 이상의 필드로 제한하려면 다음을 사용하십시오.
awk -F'\t' 'NF>3' file
답변2
grep -v "^[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+$"
여기서 grep은 해당 -E
옵션을 제공하지 않으므로 기본 정규 표현식(BRE)을 사용합니다. 확장 정규식(ERE)과 달리 +
BRE는 특별하지 않으며 자체적으로 일치합니다. 또한 표준 정규식에서 백슬래시는 대괄호 그룹 내에서 특별하지 않으므로 [\t]
백슬래시 또는 문자와 일치 t
하며 [^\t]
그 이외의 모든 것과 일치합니다.
대괄호 그룹 외부에서는 \t
표준에서 일치하는 항목을 지정하지 않으며 이는 실제로 구현마다 다릅니다. 예를 들어 GNU의 경우 grep
와 일치 t
하고 ast-open의 경우 grep
TAB 문자와 일치합니다.
표준 정규식에서 탭 문자를 일치시키려면 리터럴 탭 문자를 전달해야 합니다. grep
예를 들어 $'...'
많은 셸에서 지원하는 인용 형식을 사용합니다. (이것은 아직 표준이 아닙니다. printf
탭 문자를 얻으려면 표준 쉘에서 사용해야 합니다 .)
따라서 탭 문자 로 grep $'a\tb'
찾아서 구분하고, 또는 또는 하나 이상의 탭 문자로 찾아서 구분합니다 .a
b
grep $'a\t\t*b'
grep $'a\t\\{1,\\}b'
grep -E $'a\t+b'
a
b
답변3
좋아, 그래서 문제를 알아냈어. 사용할 수 없습니다\티grep에서는 이렇게 됩니다. 일반 문자에만 일치합니다.티.
탭 문자를 일치시키는 방법에 대한 옵션은 다음에서 찾을 수 있습니다.SO에 대한 이 질문.
명령에 -P 옵션을 추가하여 문제를 해결했으므로 다음과 같이 작동합니다.
grep -Pv "^[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+$"
다른 선택지를 지적했다@필리포스주석(4개 이상의 탭이 있는 줄만 일치). 그러나 -P 옵션도 필요합니다.
grep -P '\t.*\t.*\t.*\t'
답변4
다른 사람들이 이미 지적했듯이 \t
정규식은 TAB을 나타내지 않습니다. 따라서 확실한 해결책은 문자 그대로 TAB 문자를 추가하는 것입니다. 그러면 BASH가 약간 까다로워질 수 있습니다. 그러나 ^V
( Control+) 입력 텍스트 탭 문자를 사용할 수 있습니다 vTAB.
어쩌면 setup TAB='
Control+가 더 편리할 수도 있습니다 v TAB'
. 또 다른 방법은 +
문자 그대로 비확장 정규식(BRE)으로 처리하는 것입니다("기본 정규식과 확장 정규식” man grep
)이므로 다음을 사용하십시오.
grep -v "^[^$TAB]\+$TAB[^$TAB]\+$TAB[^$TAB]\+$TAB[^$TAB]\+$"
(여기서 변수를 로 단축할 수도 있으며 ( 또는 ) 를 T
사용할 필요는 없지만 예상치 못한 상황에 대비하세요)${TAB}
${T}
또는 원하는 경우 egrep
다음과 같이 반복 그룹을 사용할 수 있습니다.
egrep -v "^([^$TAB]+$TAB){3}[^$TAB]+$"