6

主に、私が使用するすべてのサイトがパターンマッチングを行うためのさまざまなツールを提供しているため、シェルプログラミングに完全に夢中になっています。だから私の質問は、パイプストリームで単純なパターンマッチングを行うためにどのツールを使用するかです。

コンテキスト: named.conf ファイルがあり、さらに処理するために単純なファイルにすべてのゾーン名が必要です。だから私は ~$ cat named.local | ゾーンをgrepして、ここで完全に迷子になります。私の出力は、「zone "domain.tld" {」という形式の〜100行程度の改行であり、テキストを二重引用符で囲む必要があります。

これを行う方法を示してくれてありがとう。

J

4

5 に答える 5

24

あなたが探しているのは...sed行ごとに置換を行うストリーム編集ツールだと思います。

あなたが説明しているように、コマンド `cat named.local | grep zone' を実行すると、次のような出力が得られます。

zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {

二重引用符で囲まれたテキストが必要だと言ったので、出力を次のようにしたいと思います。

"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"

したがって、実際には、各行から、二重引用符で囲まれたテキスト (二重引用符自体を含む) が必要です。

あなたが正規表現に精通しているかどうかはわかりませんが、正規表現はシェル スクリプトを作成する人にとって非常に貴重なツールです。たとえば、正規表現/.o.e/は、2 番目の文字が小文字でo4番目の文字が である単語がある行に一致しますezoneこれは、" "、" tone"、さらには " "I am tone-deaf.などの単語を含む文字列に一致します。

そこでのトリックは、.(ドット) 文字を使用して「任意の文字」を意味することでした。*「前の文字を 0 回以上繰り返す」など、他にもいくつかの特殊文字があります。したがって、次のような正規表現は、" "、" "、または空の文字列にa*一致します: ""aaaaaaaa

したがって、次を使用して引用符内の文字列を一致させることができます。/".*"/

あなたが知っている別のことがありますsed(そして、コメントによって、あなたはすでに知っています!) -バックトラックが可能です。単語の認識方法を指定したら、その単語を置換の一部として使用させることができます。たとえば、このリストを次のように変更したいとします。

Billy "The Kid" Smith
Jimmy "The Fish" Stuart
Chuck "The Man" Norris

このリストに:

The Kid
The Fish
The Man

まず、引用符内の文字列を探します。私たちはすでにそれを見ました、それは/".*"/.

次に、引用符内にあるものを使用します。括弧を使用してグループ化できます。/"(.*)"/

テキストをアンダースコア付きの引用符に置き換えたい場合は、 replace: を実行するs/"(.*)"/_/と、次のようになります。

Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris

しかし、後戻りがあります。これにより、記号を使用して、括弧内に何があったかを思い出すことができます\1。したがって、今実行すると、次s/"(.*)"/\1/のようになります。

Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris

引用符は括弧内にないため、\1!の内容の一部ではありませんでした。

二重引用符内のものだけを残すには、行全体を一致させる必要があります。そのために、^(「行頭」を意味する) と$(「行末」を意味する) があります。

したがって、 を使用するs/^.*"(.*)".*$/\1/と、次のようになります。

The Kid
The Fish
The Man

なんで?s/^.*"(.*)".*$/\1/正規表現を左から右に読んでみましょう。

  • s/-置換正規表現を開始
  • ^- 行頭を探します。そこから始めましょう。
  • .*- すべての文字を読み続けて...
  • "- ... 二重引用符に到達するまで。
  • (- 後でバックトラックするときに思い出したいキャラクターのグループを開始します。
  • .*- すべての文字を読み続けて...
  • )- (なんてこった! グループを閉じる!)
  • "- ... 二重引用符に到達するまで。
  • .*- すべての文字を読み続けて...
  • $- 行末!

  • /- この後のものを使用して、一致したものを置き換えます

  • \1- 一致した最初のグループの内容 (括弧内) を貼り付けます。
  • /- 正規表現の終わり

平易な英語では、「行全体を読み、二重引用符の間のテキストを横にコピーします。次に、行全体を二重引用符の間の内容に置き換えます。」

置換するテキストを二重引用符で囲むこともできるs/^.*"(.*)".*$/"\1"/ため、次のようになります。

"The Kid"
"The Fish"
"The Man"

これを使用しsedて、行を引用符内のコンテンツに置き換えることができます。

sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"

(これは、二重引用符やスラッシュなどを処理するためにシェルエスケープされているだけです。)

したがって、コマンド全体は次のようになります。

cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
于 2009-04-27T07:18:12.603 に答える
2

まあ、誰もcutまだ言及していないので、シェルで何かをする方法がたくさんあることを証明するために:

% grep '^zone' /etc/bind/named.conf  | cut -d' ' -f2
"gennic.net"
"generic-nic.net"
"dyn.generic-nic.net"
"langtag.net"
于 2009-04-27T11:28:58.070 に答える
1

1.

zoul@naima:etc$ cat named.conf | grep zone
zone "." IN {
zone "localhost" IN {
    file "localhost.zone";
zone "0.0.127.in-addr.arpa" IN {

2.

zoul@naima:etc$ cat named.conf | grep ^zone
zone "." IN {
zone "localhost" IN {
zone "0.0.127.in-addr.arpa" IN {

3.

zoul@naima:etc$ cat named.conf | grep ^zone | sed 's/.*"\([^"]*\)".*/\1/'
.
localhost
0.0.127.in-addr.arpa

正規表現は.*"\([^"]*\)".*で、次のものに一致します。

  1. 任意の数の任意の文字:.*
    • 見積もり:"
    • 後で覚え始めます:\(
    • 引用符以外の任意の文字:[^"]*
    • 覚えておくべき終了グループ:\)
    • 締めくくりの引用:"
    • および任意の数の文字:.*

を呼び出すときsedの構文は's/what_to_match/what_to_replace_it_with/'. 一重引用符は、正規表現が によって展開されないようにするためにありますbash。括弧を使用して正規表現内の何かを「思い出す」場合、それを などのように思い出すことができます\1\2しばらくいじってみてください。

于 2009-04-27T07:27:48.603 に答える
0

誰かが sed/awk を指摘している限り、grep は冗長であることを指摘しておきます。

sed -ne '/^zone/{s/.*"\([^"]*\)".*/\1/;p}' /etc/bind/named.conf

これにより、引用符なしで探しているものが得られます (引用符を括弧内に移動して保持します)。awk では、引用符を使用するとさらに簡単になります。

awk '/^zone/{print $2}' /etc/bind/named.conf

私はパイプラインをできるだけ避けようとしています (しかしそれ以上ではありません)。cat をパイプしないでください。必要ありません。また、awk と sed が grep の作業を複製する限り、grep もパイプしないでください。少なくとも、sed や awk には関係ありません。

個人的には、おそらくperlを使用していたでしょう。しかし、それはおそらく、あなたが perl で行っていることの残りの部分を、些細なことにしていただろうからです (そして、ファイル全体を丸呑みし、同時にすべてに対して正規表現を実行できるため、\n を無視することは、共有 Web ホストなど、/etc/bind を制御しません)。しかし、シェルでそれを行うとしたら、上記の2つのうちの1つが私がアプローチする方法になります。

于 2009-04-27T15:41:01.710 に答える
0

awkを見てください。

于 2009-04-27T07:24:15.150 に答える