web-dev-qa-db-ja.com

ASCII文字のみを含むファイル内の行を検索し、それらの行を処理するにはどうすればよいですか?

次のようなテキストファイルがあります。

English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only
Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ

真ん中には、English words onlyAlso English words onlyの2つの行が次々にあることに注意してください。

私がする必要があるのは、これらの2行を取得し、次のように/で区切られた1行に結合することです。

English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only / Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ

次の正規表現[[:ascii:]]でASCII文字を含む行を検索でき、[^[:ascii:]]で非ASCIIを検索できることがわかりました。ただし、正規表現を使用して、条件に一致するnotのインスタンスを見つけるのに少し問題があります。検索する必要があるのは行without非ASCII文字。

「逆マッチング」に関するこの質問 が見つかりましたが、答えは私を超えています。

それからもちろん、互いの関係に基づいて行を一致させることは別の問題です。これらの行が次々に並んでいるときに一致させることはできますか?それが可能かどうかさえわかりません。

非ASCII文字を含まないすべての行を検索し、LibreOffice、Gedit、またはコマンドラインを使用してそれらを結合する方法はありますか?

ファイルの長さは数千行であり、よくわからないことにも注意してください。ただし、might英語のみの行が存在する可能性があります。 3または4のグループです。

6
Questioner

[[:ascii:]]文字クラスを知らない場合でも、sedを使用してこのジョブを実行できるようです。その代わりに、CまたはPOSIXロケールを使用している限り、すべてのASCII文字を エスケープシーケンス[\d0-\d127]の範囲で指定できます。

信頼できるはずのコマンドを次に示します。

LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file

ノート

  • LC_ALL=Cこのコマンドに対してのみCロケール設定を使用します(そうしないとエラーが発生します)
  • -rコマンドを読みやすくするために拡張正規表現を使用します(バックスラッシュの必要性を減らします)(GNU sedも同じ意味で-Eを認識します)。
  • :aラベル-ループはここから始まります
  • ;シェルのようにコマンドを区切ります
  • N次の行をパターンスペースに読み込み、\nを置き換えることができます
  • s|old|new|oldnewに置き換えます
  • ^([\d0-\d127])\n([\d0-\d127]+)$-ASCIIのみの2行に一致し、\1の最初の行と\2の2行目をキャプチャします。 ^は行の始まり、\nは改行、$は行の終わりです。したがって、^line 1\nline 2$line 1line 2全体をテストします。
  • \1 / \2 1行目と2行目で、改行ではなく / で区切られています。
  • ta-最後の検索と置換コマンドが成功した場合、ループを再度実行します。これにより、ファイルのすべての行を処理し、3行以上のall-ASCII行があるインスタンスを処理できます。

Eliah Kagan に感謝します ASCII文字に一致するエスケープシーケンスの使用方法を示します =。

4
Zanna

ASCII文字のみで構成されるwhole linesが必要な場合は、パターンを行の先頭と末尾に固定する必要があります。 grep

$ grep -P '^[[:ascii:]]*$' file
English words only
English words only
English words only
Also English words only
English words only

一部のツールは、grepの-x--line-regexpなどの行全体のフラグを提供します。

   -x, --line-regexp
          Select  only  those  matches  that exactly match the whole line.
          For a regular expression pattern, this  is  like  parenthesizing
          the pattern and then surrounding it with ^ and $.

あなたが使用できるようにする:

$ grep -Px '[[:ascii:]]*' file
English words only
English words only
English words only
Also English words only
English words only

Multilineマッチングは、他の一般的なコマンドラインテキスト処理ユーティリティの多くが行ベースであるため、さらに複雑なレイヤーを追加します。 -Zフラグを使用してgrepにファイル全体を強制的に丸lurみさせることができますが、pcregrepまたはPerl自体などのツールがその時点でおそらくより適切です。

解決する必要があるnext問題は、複数行一致のコンテキストで「行の開始」と「行の終了」の概念を解釈する方法です。 Regex Tutorial:AnchorsPerlはこれらの1つであり、/m修飾子を提供します。デフォルトのレコード区切り文字の設定を解除してファイルを丸lurみする必要があります(ここでは-0777を使用して行います)。例えば

$ Perl -0777 -pe 's{^([[:ascii:]]+)\n([[:ascii:]]+)$}{$1 / $2}mg' file
English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only / Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
4
steeldriver