いくつかのパターンを抽出するためにいくつかのテキストファイルを読みました。行番号も必要ですが、最終的なgrepの前に削除する必要があります(ただし、さらなる処理のために変数を使用して保存できます)。
より良い理解のために(長い行)コマンドを分割するプロセスを説明します。
ファイルを読む猫、クリーンアップを実行します(次を使用して奇妙な文字と改行文字を削除します)。sedそしてティー)など。以下は、さまざまなダクトクリーニング作業の例です。
cat file | sed 's/,/ /g' | sed '/^$/d'
行番号とタブの追加NLコマンドと追加の処理とクリーンアップ
nl -nrz -w4 -s$'\t' | tr '\n\r' ' '
目的の最終スキーマをCSVファイルに抽出
grep -Eio '.{0,0}account number.{0,15}' >> account_list.csv
問題は、同じ行コマンド(whileまたはループは許可されていません)を使用して、ステップ2の行番号をまったく同じCSV(順序に関係なく別の列)に送信する必要がありますが、これまでは成功しませんでした。
[理解を助けるために修正しました] 必要な行番号は、クリーンアップ前のファイルの元の行番号であることを考慮すると。このクリーニングの過程で、時々詩は削除されます。千行のファイルを想像してみてください。処理後、バックラインが表示されます。新しい行番号が正しくありません。 【編集終了】
いくつかの処理後のサンプル入力:
0123 the first account number 2345356432 must be used
0345 take it just for billing purposes, not any other.
0657 Meanwhile the second account number 8623525534
0987 user is blocked until the issue is solved with
希望の出力は次のとおりです。
2345356432; 0123
8623525534; 0657
または
0123; 2345356432
0657; 8623525534
どんなアドバイスも本当にありがとうございます。
答え1
awk
クリーンアップする前に、元の入力ファイルで次を使用します。
awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print NR ";" substr($0, a[1, "start"], a[1, "length"]); }' input
その後、口座番号が抽出され、行の先頭に行番号が印刷されます。
1;2345356432
3;8623525534
クリーンアップされたファイルから前処理された数値を抽出するには、次の手順を実行します。
awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print $1 ";" substr($0, a[1, "start"], a[1, "length"]); }' input
少し分析してみてください。
/account number [[:digit:]]+/
「口座番号」の後に数字が一致する行のみを処理していることを確認してください。match($0, "account number ([[:digit:]]+)", a)
パターンを見つけて、一致するグループの位置と長さ(、数)を([[:digit:]]+)
配列に保存しますa
。print NR ";" substr($0, a[1, "start"], a[1, "length"])
レコード番号の印刷(つまり行番号、複数のFNR
ファイルを処理する場合に使用)、最初のグループに対応する部分;
文字列:開始インデックス、長さ(パディングで埋められる)をa[1, "start"]
提供します。a[1, "length"]
match
これらすべては、1行につき最大1つのアカウントがあると想定しています。
2番目のバリエーションは$1
代わりに印刷しますNR
。つまりファイルの最初のフィールドは前処理された行番号です。
答え2
あなたのgrepバージョンがPerl正規表現をサポートしている場合は、振り返ることができます:
grep -Pnio "(?<=account number.)([0-9]{0,15})" text
答え3
入力と出力を考慮すると、awkスクリプトははるかに簡単に見えます。
gawk '/account number/ {
nr=gensub(/.*account\s*number\s*([0-9]+).*/, "\\1", "g")
print FNR "; " nr
}'
もちろん、アカウントの抽出と出力形式を必要に応じて調整する必要があります。しかし、あなたはポイントを理解しています。 (この機能を使用するにはGNU awkが必要ですgensub
。)
答え4
私はこの目的のためにPerlを使いたいです。次のように動作する必要があります。
perl -ne 'print "$1; $2\n" if /^(\d+).*account number (\d+)/' input
^\d+
最初と2番目のキャプチャグループ(括弧内の部分、ここでは数字)を数字()で始め、「口座番号」という文字列と数字を含む行に印刷します。 Perlの行番号の概念を印刷するには、$.
代わりにを使用します$1
。