각 줄에 한 단어가 포함된 텍스트 파일이 있습니다. 두 개 이상의 문자가 포함되지 않은 줄을 삭제하려고 합니다. 예를 들어 파일은 다음과 같습니다.
words
books
aaa
letters
zzzz
출력 파일이 다음과 같기를 원합니다.
words
books
letters
uniq -c
then을 사용하여 단어를 그룹화하는 대신 각 단어를 개별 문자로 분리하려고 시도했지만 wc -l
if 문에 갇혔습니다. 또한 이 작업을 수행하는 더 쉬운 방법이 있어야 한다고 생각합니다. 이 문제를 해결할 수 있는 다른 방법은 생각할 수 없습니다.
답변1
당신이 의미한다고 가정특징문자 대신 (예: 또는 문자가 아니더라도 또는 ...
을 포함하는 줄을 제거하려는 경우 ):11
.
1
grep -vx -e '' -e '\(.\)\1*'
또는:
grep -vx '\(\(.\)\2*\)\{0,1\}'
즉, -v
한 문자( )로 .
시작 하고 그 뒤에 동일한 문자( \1
캡처된 콘텐츠에 대한 역참조 )가 이어지는 빈 줄( )을 제거( )합니다 . 줄이 끝날 때까지 \(...\)
0회 이상( ) 반복됩니다 ( 패턴을 시작 부분에 고정). 줄과 끝).*
-x
표준 ERE에는 역참조가 없기 때문에(BRE에만 있음) 여기서는 egrep
또는 를 사용할 수 없습니다 .grep -E
두 개 이상의 서로 다른 문자가 포함된 줄의 경우 다른 유형의 문자는 무시됩니다( [[:alpha:]]
여기에서는편지, 즉 고려되는 모든 문자알파벳순으로귀하의 지역에서):
grep -vx '[^[:alpha:]]*
[^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\1\)*[^[:alpha:]]*'
(두 줄에서 이는 두 가지 다른 모드를 전달하는 또 다른 방법입니다.) 또는:
grep -vx '[^[:alpha:]]*\([^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\2\)*[^[:alpha:]]*\)\{0,1\}'
그러면 12345aaa
(한 글자만) 또는 (문자 없음)과 같은 -+-+-+-
줄이 제거됩니다.
줄 도 제거하려면 Aaaa
(예: 문자를 비교할 때 대/소문자 무시) 이 -i
옵션을 추가하세요.
문자 수준에서 작동하므로 여러 문자로 표현되는 문자소가 있는 경우 예상한 대로 작동하지 않을 수 있습니다. 예를 들어 다음 출력과 유사한 줄을 제거합니다.
$ printf 'e\u0300e\u0301\n'
èé
(GNU printf
또는 호환 가능하다고 가정) 그러나 다음과 같지는 않습니다.
$ printf '\ue8\ue9\n'
èé
( e\u300
자소의 분해 및 \ue8
사전 결합 형태는 어디에 있습니까 è
? e
(U+0065) 및 è
(U+00E8)은알파벳순으로, 그러나 악센트/악센트와 결합된 U+0300 또는 U+0301은 제외).
pcregrep
문자소를 사용하려면 또는 GNU grep
및 해당 옵션을 사용할 수 있습니다 -P
.
첫 번째 경우(적어도 두 개의 서로 다른 문자소 클러스터):
grep -vxP '(?:(\X)\1*)?'
두 번째 경우(적어도 두 가지 다른 경우가 있습니다.편지자소 클러스터):
grep -vxP '(?:(?=\PL)\X)*(?:((?=\pL)\X)(?:(?:(?=\PL)\X)*\1(?!\pM))*(?:(?=\PL)\X)*)?'
(?=\PL)\X
비알파벳 문자소 클러스터( 비알파벳( ) 및 알파벳 문자소 클러스터 로 시작하는 \X
경우 문자소 클러스터( )) 는 어디에 있습니까?(?=...)
\PL
(?=\pL)\X
\pL
성냥편지유니코드를 수정하세요. POSIX 문자 클래스와 달리 [:alpha:]
알파벳이 아닌 스크립트의 문자도 포함됩니다.
e\u300\u301
, , 가 모두 날카롭고 악센트가 있는 a e\u301\u300
인 경우에도 4개의 서로 다른 클러스터로 처리 됩니다 \ue9\u300
.\ue8\u301
e
ffi
또한 한 문자에 여러 문자가 포함된 (U+FB03)과 같은 문자 에 주의하세요.특징.
PCRE를 사용하면 다음을 수행할 수도 있습니다.긍정적인방법:
최소 2개의 다른 문자:
grep -P '(.).*(?!\1).'
최소 2개의 서로 다른 알파벳 문자:
grep -P '(\pL).*(?!\1)\pL'
최소 2개의 서로 다른 문자소 클러스터:
grep -P '^\X*(\X)\X*(?!\1(?!\pM))\X'
(적어도) 꾸란 한국어의 분해된 형태는 제대로 작동하지 않습니다. PCRE(
perl
RE 와 반대\b{g}
)에는 AFAIK(자소 경계 연산자)가 없으며 유니코드 속성에 대한 지원이 제한되어 있습니다. 우리는(?!\pM)
근사치로 (이 경우 "결합 표시 문자가 따르지 않는 한"을 의미함)를 사용 하지만 이는 여러 부분으로 구성된 한글에서는 작동하지 않습니다.편지/음절그 중에서도 캐릭터부분그런 재산은 없습니다.려련련
예를 들어 삭제합니다. 이제 모든 사람은 다음과 같이 주장할 수도 있습니다.부분독특하다편지...perl
버전 5.22 이상의 경우 다음과 같이 작성할 수 있습니다.perl -Mopen=locale -lne 'print if /\b{g}(\X).*\b{g}(?!\1\b{g})\X/'
적어도 2개의 다른편지문자소 클러스터:
grep -P '^\X*((?=\pL)\X)\X*(?!\1(?!\pM))(?=\pL)\X'
다시 말하지만 에는 적용되지 않습니다
려련련
.perl
perl -Mopen=locale -lne 'print if /\b{g}(?=\pL)(\X).*\b{g}(?!\1\b{g})(?=\pL)\X/'
이를 통해 perl
다음과 같은 보다 직접적인 접근 방식을 사용할 수 있습니다.
최소 2개의 다른 문자:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/./g) >= 2'
최소 2개의 서로 다른 알파벳 문자:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/\pL/g) >= 2'
최소 2개의 서로 다른 문자소 클러스터:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/\X/g) >= 2'
적어도 2개의 다른편지문자소 클러스터:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(grep /^\pL/, /\X/g) >= 2'
답변2
예상되는 결과에 따라 두 단어 이상을 건너뛰고 싶습니다.정확히 똑같다수치:
grep방법:
grep -vE '(.)(\1){2,}' file
산출:
words
books
letters
파일 수정제자리에다음을 적용할 수 있습니다.sed방법:
sed -Ei '/(.)(\1){2}/d' file
답변3
쿼리에 대한 정방향 검색:
while read -r line; do
n=$(echo "$line" | egrep -o . | sort -u);
[[ ${#n} -gt 1 ]] && echo "$line";
done < file