2つの単語のうち1つだけを含め、両方を含まない行数を計算する方法

2つの単語のうち1つだけを含め、両方を含まない行数を計算する方法

テキストファイル()でsumという単語を含む行数を数える必要がありますtheanpoem.txt同時に両方ではありません

使ってみました。

grep -c the poem.txt | grep -c an poem.txt

theしかし、合計合計数がan9行の場合、6という誤った答えが出ます。

単語自体ではなく単語を含む行数を計算したいです。実際の単語だけが計算されるのでandではtheありませんが。thereanPan

サンプルファイル:poem.txt

Where is the misty shark?
Where is she?
The small reef roughly fights the mast.
Where is the small gull?
Where is he?
The gull grows like a clear pirate.
Clouds fall like old mainlands.

She will Rise calmly like a dead pirate.
Eat an orange.
Warm, sunny sharks quietly pull a cold, old breeze.
All ships command rough, rainy sails.

Elvis Aaron Presley also known simply as the Elvis
He is also referred to as the King
The best-selling solo music artist of all time
He was the most commercially successful artist in many genres

He has many awards including a Grammy lifetime achievement
Elvis in the 1970s has numerous jumpsuits including an eagle one.

追加の説明:この時点でorを含む行数は何ですか?ただし、すべてのandを含む行は計算しないでtheください。anthean

the car is red - this counted
an apple is in the corner - not counted
hello i am big - not counted
where is an apple - counted

したがって、ここで出力は2でなければなりません。

編集:大文字と小文字の区別は心配しません。

強調表示された単語のスクリーンショット

最終編集:すべての助けに感謝します。この問題を正常に解決しました。答えの1つを使用していくつか変更しました。cat poem.txt | grep -Evi -e '\<an .* the\>' -e '\<the .* an\>' | grep -Eci -e '\<(an|the)\>追加情報を得るために2番目のgrepをaに変更した方法です。すべての助けにもう一度ありがとう! :)-c-n

答え1

perl -nE 'END {say $c+0} ++$c if /\bthe\b/i xor /\ban\b/i' file
gawk 'END {print c+0} /\<the\>/ != /\<an\>/ {++c}' IGNORECASE=1 file

各式の一致結果を比較すると、所望の結果が得られる。

たとえば、一致結果は\<the\>0または1です。他の一致の結果が同じ場合、両方の正規表現が見つかったり見つからず、その行は計算されません。異なる場合、一致するものの1つが見つかりましたが、他のものは見つからなかったことを意味するため、カウンタが増加します。

gawkには次のxor()機能が組み込まれています。

gawk 'END {print c+0} xor(/\<the\>/,/\<an\>/) {++c}' IGNORECASE=1 file

答え2

grepを使用してください:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eci -e '\<(an|the)\>'

これが重要です一致する線。合計を計算する代替構文を見つけることができます。マッチ以下に。

分解:

まず、grepコマンドは、「an」と「the」を含むすべての行をフィルタリングします。 2番目のgrepコマンドは、「an」または「the」を含む行数を数えます。

c2番目のgrepから削除すると、-Eciすべての一致が強調表示されます。

詳細:

  • この-Eオプションはgrepの拡張式構文(ERE)を有効にします。

  • この-iオプションは、grepが大文字と小文字を区別せずに一致するように指示します。

  • この-vオプションはgrepに結果を逆にするように指示します。いいえインクルードモード)

  • この-cオプションは、grep に行自体ではなく一致する行数を出力するように指示します。

  • モデル:

    1. \<単語の始まりと一致します(ありがとう@glenn-jackman)
    2. \>単語の終わりの一致(ありがとうございます。@glenn-jackman)

    -->これにより、単語が一致しないことを確認できます。含む「the」または「an」(例:「pan」)

    1. grep -Evi -e '\<an\>.*\<the\>'したがって、すべての行に一致いいえ「a...」が含まれています。

    2. 同様にgrep -Evi -e '\<the\>.*\<an\>'、すべての行を一致させます。いいえ「...an」を含みます。

    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>'3.と4.の組み合わせです。

    4. grep -Eci -e '\<(an|the)\>'「an」または「the」(スペースまたは行の先頭/末尾で囲まれている)を含むすべての行に一致し、一致する行数を印刷します。

編集1:@glenn-jackmanが提案したように、andの代わり\<\>and( |^)を使用してください。( |$)

編集2:一致する行数の代わりに一致数を計算するには、次の式を使用します。

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eio -e '\<(an|the)\>' \
  | wc -l

これは、各一致を別々の行に印刷してから(他の項目なし)、行数を数える-ogrepオプションを使用します。wc -l

答え3

次のGNUawkプログラムはこの問題を解決する必要があります。

awk '(/(^|\W)[Tt]he(\W|$)/ && !/(^|\W)[Aa]n(\W|$)/) || (/(^|\W)[Aa]n(\W|$)/ && !/(^|\W)[Tt]he(\W|$)/) {c++} END{print c}' poem.txt

c次の場合、カウンタがインクリメントされます。

  • 行は一致しますが(^|\W)[Tt]he(\W|$)(最初の文字はthe大文字と小文字が区別されませんが、前に非単語コンポーネント()または行の\W先頭() 、後に単語以外のコンポーネント()または行末()が続きます)は一致しません(分離最初 - 文字を区別せずに書く) - または -^\W$(^|\W)[Aa]n(\W|$)an
  • 線は一致します(^|\W)[Aa]n(\W|$)が一致しません。(^|\W)[Tt]he(\W|$)

最後に印刷された値ですc

\<「単語の開始」と「単語の終わり」として、およびを使用して\>少し短くすることができます。

awk '(/\<[Tt]he\>/ && !/\<[Aa]n\>/) || (/\<[Aa]n\>/ && !/\<[Tt]he\>/) {c++} END{print c}' poem.txt

短いのは次のとおりです。

awk '/\<[Tt]he\>/ != /\<[Aa]n\>/ {c++} END{print c}' poem.txt

an不等式は、合計の1つが線に表示されるか、両方が表示されない場合にのみ真ですthe

and / 構成は正規表現構文を拡張するGNU拡張であるawkため、このアプローチにはGNUが必要です(しかし、次のように理解することもできます)。\W\<\>\<\>BSD正規表現)。

ファイルを入力引数として呼び出すことはstdinで読み取るものを置き換えるため、試したソリューションに示したパイプライン構成は機能しません。grepしたがって、パイプラインの最初の部分は目立たずに消え、出力は完全に最後の部分によって引き起こされます(発生an、つまり別の言葉で含まれている場合でも同様です)。

答え4

GNU grepとPCREの長さがゼロのアサーションを使用してこれを実行できます。

grep -iP '(?=.*\bthe\b)(?!.*\ban\b)|(?=.*\ban\b)(?!.*\bthe\b)' poem.txt

Where is the misty shark?
...
Eat an orange.
...

grep -ciP '(?=.*\bthe\b)(?!.*\ban\b)|(?=.*\ban\b)(?!.*\bthe\b)' poem.txt

9

Perl(元の場所)でも同じ機能を使用でき、GNU grepが存在しないシステムにもPerlが存在する可能性があります。

関連情報