正確な番号と通り名を渡して、さまざまな数字を含む自宅住所のテキスト内で文字列を見つけます。

正確な番号と通り名を渡して、さまざまな数字を含む自宅住所のテキスト内で文字列を見つけます。

コンテキスト

私は郵便の従業員(メール分類器)で、正確な通りの住所と通りの名前の最初の数文字を入力し、パス番号情報文字列を含む一致する文字を返すbashスクリプトを作成しようとしています。 。私は毎日手紙を見て、都市のすべての住所が書かれた巨大なポスターを見て、処理できない何千もの手紙を分類しなければなりませんでした。このスクリプトを使用すると時間が節約されるため、スクリプトを完了するプロセスを学ぶために最善を尽くしています。私はUNIX / Linuxスクリプトについて同様の趣味を持っています。ここで、正規表現が解決策であるか、grep、find、awk、sed、またはその両方のバリエーションであるかはわかりません。

住所リスト(自宅番号の範囲と通り名)を含むテキストファイルがあり、各住所は次のように改行されています。

6974-7075 hwy 99: ss1
7757-8079 hwy 99: ss14
98-258 even foo st N: 15
97-257 odd foo st N: 16
21-301 foo st S: 17
15-20 foo st S: 7
bar st: 1
fake st: 31
fake pl: 77
sample dr: 89

番号範囲、ルートの距離(自宅番号は指定されていません)、偶数と奇数の指定子、道路の種類(st、hwy、pl、drなど)、北(N)と南(S)の指定子があることを確認してください。そして最後に、コロンの次はパス情報です。

現状

テキストファイルとまったく同じ距離番号を入力する限り、目的の文字列を返す次のスクリプトがあります。

#! /bin/bash

civic="$1"
street="$2"

grep $civic.*$street /path/to/addresses.txt 

実行されたか、./script.sh 7757私に./script.sh 7757 h返されます。7757-8079 hwy 99: ss14コロンの後ろのパスだけでなく、文字列全体がここに返されることが好きです。しかし、明らかに私のコードは範囲内の数字をチェックしなかったので、実行は./script.sh 8020 h返されません。7757-8079 hwy 99: ss14

助けが必要です

しかし、8020が7757から8079の範囲にあるので、8020 h入力して戻り続ける方法を探しています。7757-8079 hwy 9: ss14

また、foo stにはNとSのインジケータだけでなく、さまざまなパスの偶数と奇数の範囲があることをテキストで参照してください。家番号が変で帰る必要なく入ったり107 f戻っ107 fooたりする方法を探しています。これらの偶数/奇数の場合、単語の偶数/奇数は常に文字列に割り当てられているため、入力された家の番号が奇数の場合はgrepを使用するか、数値範囲内の文字列からこれらの単語を検索できますか?この例では、家の番号が範囲内にあり、文字列に奇数があるため(foo st Sを参照)も返されます。 NやSを指定する時間がないため、NとSを返すことに同意します。97-257 odd foo st N: 1698-258 even foo st N: 1521-301 odd foo st S: 17

完全な答えであれ、より詳細なヒントであれ、私の努力にご協力いただきありがとうございます。問題を起こそうとしたのではなく、ただ助けを求めるだけです!より具体的に説明できれば教えてください。

答え1

#! /bin/bash

civic="$1"
street="$2"

if [ "$((civic%2))" = 1 ]; then
   exclude=" even "
else
   exclude=" odd "
fi

</path/to/addresses.txt grep "$street" \
   | grep -v "$exclude" \
   | awk -F '[ -]' -v civic="$civic" '
      {if ($1 !~ /^[0123456789]*$/ || $2 !~ /^[0123456789]*$/) print
       else if (civic>=$1 && civic<=$2) print}
     '

ステップ:

  1. 数字が奇数か偶数かを確認し、それに応じて除外文字列を準備します。
  2. 最初は、grep距離に一致する線を選択します。すべての行は空の文字列と一致するため、距離を指定しないと、このステップですべての行が一致します。
  3. 2番目grepのステップでは、最初のステップの除外文字列を使用して、「奇数」または「偶数」と記載されている項目を除外します。
  4. awkスペースを区切り文字として使用して、各行を分割します-。最初の 2 つのフィールドのいずれかが正確に数値でない場合、範囲は指定されず、行が印刷されます。それ以外の場合は、明らかに最初の2つのフィールドが範囲を定義します。その後、数値が範囲に対してテストされ、範囲内にある場合、行が印刷されます。

答え2

包装紙awkが付属しています。bash別の名前で保存script.shして実行可能にします。

#!/bin/bash

filename="data.txt"

n="$1"       # save number from argument list
shift        # remove number from argument list
s="$@"       # save remaining argument list
s="${s:=.*}" # set regex .* as default if street is missing

awk -v number="$n" -v street="$s" '
BEGIN{
  FS="-| "   # use field separator "-" or one space to split current row
}

$0 ~ street{
  # current row contains street

  if( $1 ~ /^[0-9]+$/ && $2 ~ /^[0-9]+$/ ){
    # current row starts with a range

    if( number >= $1 && number <= $2 ){
      # number is in expected range

      if ( $3 == "odd" || $3 == "even" ){
        # string "even" or "odd" found

        if ( $3 == "odd" && number ~ /[13579]$/ ){
          # odd
          print
        }

        if ( $3 == "even" && number ~ /[24680]$/ ){
          # even
          print
        }
      } else {
        # neither "even" or "odd" found
        print
      }
    }
    # finished with current row
    next
  }
  # match but no range found in current row
  print
}
' "$filename"

関連情報