各行に1つの単語を含むテキストファイルがあります。複数の文字を含まない行を削除しようとしています。たとえば、ファイルは次のようになります。
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文字()で.
始まり、その後に同じ文字(\1
キャプチャされたコンテンツの逆参照)が続く空白行()を削除()します。行が終わるまで\(...\)
0回以上()繰り返されます(パターンを先頭に固定)。行と終わり)。*
-x
標準EREには逆参照がないため(BREのみ)、ここではegrep
またはを使用できません。grep -E
2つ以上の異なる文字を含む行の場合、他の種類の文字は無視されます([[:alpha:]]
ここでは手紙、つまり考慮されるすべての文字アルファベット順にあなたの地域で):
grep -vx '[^[:alpha:]]*
[^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\1\)*[^[:alpha:]]*'
(2行でこれは2つの異なるモードを渡す別の方法です。)または:
grep -vx '[^[:alpha:]]*\([^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\2\)*[^[:alpha:]]*\)\{0,1\}'
これにより、12345aaa
(1文字のみ)や(文字なし)などの-+-+-+-
行が削除されます。
行を削除するにはAaaa
(たとえば、文字を比較するときに大文字と小文字を無視する)、この-i
オプションを追加します。
文字レベルで機能するため、複数の文字で表される文字がある場合は、期待どおりに機能しない可能性があります。たとえば、次の出力に似た行を削除します。
$ printf 'e\u0300e\u0301\n'
èé
(GNUprintf
または互換性があると仮定)しかし、次のようなものではありません。
$ printf '\ue8\ue9\n'
èé
(e\u300
磁素の分解および\ue8
プレ結合形態はどこにありますかè
?e
(U+0065)およびè
(U+00E8)はアルファベット順にただし、アクセント/アクセントと組み合わせたU+0300またはU+0301は除く)。
pcregrep
文字を使用するには、またはGNUgrep
とそのオプションを使用できます-P
。
最初のケース(少なくとも2つの異なる文字列クラスタ):
grep -vxP '(?:(\X)\1*)?'
2番目のケース(少なくとも2つの異なる場合があります)。手紙磁素クラスタ):
grep -vxP '(?:(?=\PL)\X)*(?:((?=\pL)\X)(?:(?:(?=\PL)\X)*\1(?!\pM))*(?:(?=\PL)\X)*)?'
(?=\PL)\X
アルファベット文字以外のクラスター(非アルファベット()とアルファベット文字スペースクラスターで始まる\X
場合、文字スペースクラスター())はどこにありますか?(?=...)
\PL
(?=\pL)\X
\pL
マッチ手紙Unicodeを編集してください。 POSIX 文字クラスとは異なり、アルファベット以外のスクリプト[:alpha:]
の文字も含まれます。
e\u300\u301
、 、 がすべて鋭くアクセントのあるaであってe\u301\u300
も、4つの異なるクラスタとして扱われます\ue9\u300
。\ue8\u301
e
ffi
また、1文字に複数の文字を含む(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(子境界演算子)がなく、Unicode属性のサポートが制限されています。私たちは(?!\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
予想される結果に応じて、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