ファイルから渡されると、awkでは変数は許可されません。

ファイルから渡されると、awkでは変数は許可されません。

ファイルを一行ずつ読み込んでいます。各行は次のようになります。

xxyu: JHYU_IOPI

各行は以下のようにawkに渡されます。パターンに一致する前の行を印刷したいです。 grepを使ってこれを行うことができ、awkでどこでミスをするのか知りたいです。

#!/bin/bash
while read i
do
 awk '/$i/{print a}{a=$0}' ver_in.txt
done<in.txt

私もこれを試しました:

#!/bin/bash
while read i
do
 awk -v var="$i" '/var/{print a}{a=$0}' jil.txt
done<in.txt

編集:sh readを使用しないようにアドバイスを受けた後、awkを使用しました。私の入力と希望の出力は次のとおりです。

編集1:@ Ed Mortonのawkスクリプトへの入力を次のように編集しました。

入力ファイル:catファイル

/* ----------------- AIX_RUN_WATCH ----------------- */ 

insert_job: AIX_RUN_WATCH   job_type: BOX 
owner: root
permission: 
date_conditions: 1
days_of_week: su
start_times: "22:00"
alarm_if_fail: 1
alarm_if_terminated: 1
group: app
send_notification: 0
notification_emailaddress: 


 /* ----------------- AIX_stop ----------------- */ 

 insert_job: AIXstop   job_type: CMD 
 box_name: AIX_RUN_WATCH
 command: ls
 machine: cfg.mc
 owner: root
 permission: 
 date_conditions: 0
 box_terminator: 1
 std_out_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stdout"
 std_err_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stderr"
 alarm_if_fail: 1
 alarm_if_terminated: 1
 group: app
 send_notification: 1


 /* ----------------- AIX_start ----------------- */ 

 insert_job: AIX_start   job_type: CMD 
 box_name: AIX_RUN_WATCH
 command: ls
 machine: cfg.mc
 owner: root
 permission: 
 date_conditions: 0
 box_terminator: 1
 std_out_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stdout"
 std_err_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stderr"
 alarm_if_fail: 1
 alarm_if_terminated: 1
 group: app

   cat targets
     box_name: AIX_RUN_WATCH

予想出力 -

 box_name: AIX_RUN_WATCH
 insert_job: AIX_stop
 insert_job: AIX_start

答え1

最初の試みでは、シェル変数拡張に二重引用符を使用してから、$awk演算子をエスケープしてシェル拡張を防ぐ必要があります。ただし、変数にawk$iなどの特殊文字(たとえば、、)が含まれていることに注意してください。 [今は、コマンドに関連する1つ以上の他の問題を解決することをスキップします]。\/

while read i
do
 awk "/$i/{print a}{a=\$0}" ver_in.txt
done<in.txt

2番目の試みでは、現在の行で正規表現一致または文字列一致を使用する必要があります。たとえば、正規表現一致(部分正規表現一致)を使用します。

while read i
do
 awk -v var="$i" '$0 ~ var{print a}{a=$0}' jil.txt
done<in.txt

または、次の文字列一致(完全な文字列一致)です。

while read i
do
 awk -v var="$i" '$0==var{print a}{a=$0}' jil.txt
done<in.txt

パターンに一致する前の行を印刷するために使用したいコマンドについて話したら、awkを使用してすべての操作を実行してから、完全な文字列一致を実行するシェルループの使用を停止できます。

awk 'NR==FNR { str[$0]; next }
($0 in str) && prev!="" { print prev } { prev=$0 }' in.txt ver_in.txt

または部分正規表現マッチングを実行します。

awk 'NR==FNR { patt[$0]; next }
{ for(ptrn in patt) if($0 ~ ptrn && prev!="") print prev; prev=$0 }' in.txt ver_in.txt

または部分文字列マッチングを実行します。

awk 'NR==FNR { strings[$0]; next }
{ for(str in strings) if(index($0, str) && prev!="") print prev; prev=$0 }' in.txt ver_in.txt

または、完全正規表現マッチングを実行します。

awk 'NR==FNR { patt[$0]; next }
{ for(ptrn in patt) if($0 ~ "^"ptrn"$" && prev!="") print prev; prev=$0 }' in.txt ver_in.txt

答え2

このために読み込み中にループは必要なく、shでテキストを処理するのは悪い考えです(参照シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?)。

代わりに、awkスクリプトに両方のファイルを処理させるようにしてください。

awk 'NR==FNR { re = $0 "|" re ; next}; # append input line and | to re
     FNR == 1 { sub(/\|$/,"",re) };    # remove trailing | on 1st line of 2nd file

     $0 ~ re { print a }; # if the current line matches re, print a
     {a = $0}' in.txt ver_in.txt

最初のファイル()を読み取るときに、各入力行と「交互」の正規表現を追加して、呼び出される変数に正規in.txt表現を作成します(例:reまたは)オペレータ。

最初のファイルの読み取りが終わったら、最初にすべきことは削除|ですrereいつも|それは構成方式のために結局性格を持つようになります。これを削除しないと、その末尾|のために正規表現がver_in.txt

その後、a現在の入力行が変数の正規表現と一致する場合は、変数をre印刷します(ver_in.txtの最初の行が一致するとaが空であるため、空行が印刷されます。reこれが発生しないようにするには、行$0 ~ re {print a}をから)してください$0 ~ re && a != "" {print a}

次に、一致するかどうかに関係なく設定しますa=$0

注:これは、NR==FNR {... ; next}最初の入力ファイルを2番目と後続の入力ファイルとは異なる方法で処理するための非常に一般的なawk慣用語です。 NRは、読んでいるすべてのファイルのグローバルラインカウンタ、FNR現在のファイルのラインカウンタです。したがって、これはNR==FNR最初のファイルを読んでいるという意味です。このnextステートメントは、次の入力行にジャンプして、残りの awk スクリプトが最初のファイルで実行されるのを防ぎます。

完全なデータサンプルを提供していないので、私は自分でテストしました。

$ cat in.txt 
xxyu: JHYU_IOPI
foo
bar

この in.txt ファイルは次のとおりです。bar|foo|xxyu: JHYU_IOPI

ちなみに、awkスクリプトは正規表現マッチングを実行するため、そのre行はin.txt固定テキストではなく正規表現として扱われます。つまり、in.txtの正規表現特殊文字(例えば、.など|)をリテラル文字として扱うには、バックスラッシュでエスケープする必要があります...これを行う必要があります[]元のshでも動作します。 +awkループ。

$ cat ver_in.txt 
a line 1
xxyu: JHYU_IOPI
b line 3
d line 4
bar
e line 6
f line 7
foo

上記のawkスクリプトの出力:

a line 1
d line 4
f line 7

答え3

テキストを操作するためにシェルループを使用しないでください。シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?。シェルを発明した人は、シェルがテキストを操作するために呼び出すawkも発明しました。

すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ cat tst.awk
NR==FNR {
    tgts[$0]
    next
}
$0 in tgts {
    if ( $0 != prevTgt ) {
        print $0
        prevTgt = $0
    }
    print prevLine
}
{ prevLine = $1 FS $2 }

$ awk -f tst.awk targets file
box_name: AIX_RUN_WATCH
insert_job: AIXstop
insert_job: AIX_start

元の答え:

awk '
    BEGIN { RS=""; FS="\n" }
    $2 != prev {
        print $2
        prev = $2
    }
    { print $1 }
' file
ght: ertyjk
xxx: rtyuiol
xxx: ertyuikl_fghjk
xxx: qwertyujkl
xxx: rtyuiol_123
ght: YUIOPO
xxx: rtyuiol
xxx: rtyuiopfghj
xxx: dfghjkvbnm
xxx: qzdfghnbvfgh
xxx: qsxcvghuiokmnhgf

バラよりhttps://www.gnu.org/software/gawk/manual/gawk.html#Multiple-LineRSをnullに設定する方法を学ぶ複数行のレコードを処理してFSを改行に設定すると、そのレコードの各フィールドは完全な行なので、データは空行で区切られたレコードとして処理され、各レコードには2つのデータ行が含まれますになります。

どの行を印刷する必要があるかを示す別のght行ファイルがあると述べました。これは、印刷しない他のブロックがあることを意味します。そのようなファイルがある場合は、次のようになります。

$ cat targets
ght: ertyjk
ght: YUIOPO

そして、他の入力ファイルには上記とght:一致しないいくつかの行が含まれています。たとえば、ght: whatever以下の変更された入力ファイルのブロックを参照してください。

$ cat file
xxx: rtyuiol
ght: ertyjk

xxx: ertyuikl_fghjk
ght: ertyjk

xxx: qwertyujkl
ght: ertyjk

xxx: rtyuiol_123
ght: ertyjk

xxx: foo
ght: whatever

xxx: bar
ght: whatever

xxx: rtyuiol
ght: YUIOPO

xxx: rtyuiopfghj
ght: YUIOPO

xxx: dfghjkvbnm
ght: YUIOPO

xxx: qzdfghnbvfgh
ght: YUIOPO

xxx: qsxcvghuiokmnhgf
ght: YUIOPO

これにより、上記のコードは次のように更新されます。

awk '
    BEGIN { FS="\n" }
    NR==FNR {
        tgts[$0]
        next
    }
    $2 != prev {
        if ( inTgts = ($2 in tgts) ) {
            print $2
        }
        prev = $2
    }
    inTgts { print $1 }
' targets RS='' file
ght: ertyjk
xxx: rtyuiol
xxx: ertyuikl_fghjk
xxx: qwertyujkl
xxx: rtyuiol_123
ght: YUIOPO
xxx: rtyuiol
xxx: rtyuiopfghj
xxx: dfghjkvbnm
xxx: qzdfghnbvfgh
xxx: qsxcvghuiokmnhgf

関連情報