grep(/sed/awk) 月の範囲

grep(/sed/awk) 月の範囲

解決策を探しましたが、この特定の問題(Googleに入力する必要がある単語が多すぎる)に対する解決策を見つけるのは少し難しいです。

したがって、次のデータを含むファイルがあります(関連のないデータは省略されます)。

... ... 2014年1月1日 ... ... ...
... ... 2014年1月2日 ... ... ...
(...)
... ... 2014年3月1日 ... ... ...
(...)

データが日付別にソートされていると想定できます。それで私がやりたかったことの1つが月の範囲に合うラインをキャプチャすることでした。たとえば、範囲が2月から4月までの場合は、月の列に、およびを含むFebすべての行を取得したいと思います。MarApr

問題を明示せずに要求を少し抽象化するために、特定のパターンに一致する最初の行を取得し、他のパターンが最後に表示されるまで、その時点からすべての行をキャプチャしたいと思います。特定のパターンが一緒にグループ化されます)。

またはを使用して、同様の問題に対するいくつかの解決策を見つけましたgrep。この状況では、どちらが最善かわかりません。sedawk

これはすべてbashスクリプトで行われるので、すべての月"コード"を含む配列[ Jan、、、、 ... Feb]Marを持って、私が望む範囲にあるかどうかを確認しようとしました。この問題に対するよりエレガントな解決策になります。

編集: @jasonwryan まあ、実際にスクリプトに範囲を指定したので、 './script.sh --month "Jan, Apr"'はデータファイルを毎月ソートしてからすべての範囲をgrepできる必要があります(この場合は1 〜4月)。したがって、awk '/Feb|Apr|May/'はこの場合は機能しますが、2月から11月までを望む場合は異なります(awk '/Feb|Mar|Apr|May|Jun|Jul|Aug |Sept| 11/'ファイル)。したがって、任意の範囲に基づいて自動化することは困難です。また、月に1回以上(毎日利用可能)のキューが必要です。指定するのを忘れました。

ベストアンサー1

mrng(){ sed "$(set -f;unset IFS rng l;n=' 
';[ -n "$ZSH_VERSION" ] && emulate sh                
prng()  for m do rng=${r%%"$m"*}${r##*"$m"} _l=$((_l+1))
                 printf "\n\n%s\n/$pat/{\n\t:$l.$_l\n\tn" $m
                 printf "\n\n%s\n\t/$pat/b$l.$_l.0" $rng
                 printf "\n\tb$l.$_l\n\t:$l.$_l.0\n}"
        done                                        
pat=$(  printf %s "${1:-%m}$n"| sed -n 's/%/&&/g;l'|
        sed ":n$n\$!N;s/\\\\\n//;tn${n}s/\$$//"); shift
r=$(    locale -c LC_TIME|sed '4!d;y/;/ /')       
for m do case   $m      in      (-)     rng=$r  ;;
        (-*)    rng=${r%%"${m#-}"*}${m#-}       ;;
        (*-)    rng=${m%-}${r##*"${m%-}"}       ;;     
        (*-*)   rng=${m%%-*}${r##*"${m%%-*}"}   ;        
                case    $rng    in      (*${m##*-}*)     
                rng=${rng%%"${m##*-}"*}${m##*-}  ;;(*)   
                rng=$rng\ ${r%%"${m##*-}"*}${m##*-};;esac
        ;;esac; : $((l+=1))                                                
        prng    ${rng:="$m"}; unset rng                                    
done|   sed "   1d;s/.*\(...\)\(\n\)\(.*[^%]\(%%\)*\)%m/\2\1\2\3\1/
                /./!{N;N$n};/\n/D"
);d"       
}

これはシェル関数です。この方法で呼び出すには、シェルスクリプトに適用するか、現在のシェルで評価する必要があります。次のように呼び出すことができます。

mrng "$pat" Jan-Mar Jun Sep-Nov <infile

-また、次のようなオープンレンジも可能です。みんなまたはMar-3月から12月まで。主張はそうではありません持つ範囲の指定 - 上記のようにすべてJunです。

しかし、実際には月名をまったく解釈せず、localeユーティリティから収集します。(これは依存関係です)そして、現在のロケールで3文字の月名を使用して動作します。

実際には、ほぼすべての範囲でサラウンド範囲を実行できます。するサラウンド、またはおそらくより良い表現でとにかく蓄積してください。

最初の引数はsed互換性のあるBREスキーマであると期待します。例外は、月名が出ると予想される場所ごとに使用する必要があることです%m。 sを複数挿入することもできます%mMar...Mar- と同じ行だけを一致させたい場合でも、これを実行できますJun...Jun。たぶんこれはあまり役に立たないかもしれませんが、おそらく…?

複雑に見えますが、その半分以上が引数解析のためのものです。sed結局、比較的簡単です。たとえば、これを行うと:

mrng %m Dec-Jan

sed...次のスクリプトが生成されます。

/Dec/{
        :1.1
        n
        /Jan/b1.1.0
        /Feb/b1.1.0
        /Mar/b1.1.0
        /Apr/b1.1.0
        /May/b1.1.0
        /Jun/b1.1.0
        /Jul/b1.1.0
        /Aug/b1.1.0
        /Sep/b1.1.0
        /Oct/b1.1.0
        /Nov/b1.1.0
        b1.1
        :1.1.0
}
/Jan/{
        :1.2
        n
        /Feb/b1.2.0
        /Mar/b1.2.0
        /Apr/b1.2.0
        /May/b1.2.0
        /Jun/b1.2.0
        /Jul/b1.2.0
        /Aug/b1.2.0
        /Sep/b1.2.0
        /Oct/b1.2.0
        /Nov/b1.2.0
        /Dec/b1.2.0
        b1.2
        :1.2.0
};d

...結局、多くのコードが生成され、ほとんどの場合評価されません。一般的な行では、Decと一致することを確認し、そうでなければJanと一致することを確認し、それ以外の場合は出力から削除します。

しかし、これらのパターンのいずれかと一致すると、単純な分岐ループが始まります。したがって、上記の例では、行がDecと一致すると印刷され、n外部入力ラインで上書きされます。新しい行がランダム月と一致する場合しかし、12月、sed b牧草地のラベル:1.1.0- これはラインがまだ評価されていないことを意味しますJan。同様に処理されますが、どの月にも評価されません。今後12月を除いて一致する月がない場合は、ラベルsed bの上に移動して行を印刷して拡張子を引きます。:1.1n

これにより、範囲の各月に対して-上記のような関数(それぞれ固有のラベルが付いています)が生成されます。:これは、コマンドライン引数が累積効果を持つことを意味します。いくつかの例:

printf %s\\n 'not a month' May 'not a month' 'also not a month' Apr |
m_rng %m Apr May

上記は次のとおりです。

May
not a month
also not a month

入力ではMay前に来、コマンドラインでは後に来るからAprです。Aprしかし、これはやや粗雑な経験的方法です。入力はコマンドライン引数の順序で処理されますが、サイクル全体が完了すると処理が再開されます。

printf %s\\n 'not a month' May 'not a month' 'also not a month' Jun Apr |
m_rng %m Apr May

...印刷...

May
not a month
also not a month
Apr

ループが中断されるため、そのJun行は削除され、次の入力行で処理が再び上から始まりますApr

とにかく、パターンには次のものを使用する必要があります。

mrng '^\([^ ]\{1,\}  *\)\{3\}%m' [month args]

おすすめ記事