
次の形式のデータを含むファイルがあります。一緒に存在し、予測可能なパターンを持つ必要がある3つの行があります。
dn: uid=N-NAME-02, ou=data01, dc=data02, dc=data03
uidNumber: 3423
sambaSID: S-1-1-11-1111111-111111111-11111111-12342
<blank line>
dn: uid=N-NAME-03, ou=data01, dc=data02, dc=data03
uidNumber: 3245
sambaSID: S-1-1-11-1111111-111111111-11111111-32212
3つのグループの2番目のデータ文字列に基づいていくつかの数学を実行し、計算結果をそのグループの3番目の文字列に入力する必要があります。
dn: uid=NAME02, ou=data01, dc=data02, dc=data03
uidNumber: (3423 + 2 * 100)
sambaSID: S-1-1-11-1111111-111111111-11111111-342500
<blank line>
dn: uid=NAME03, ou=data01, dc=data02, dc=data03
uidNumber: (3245 + 2 * 100)
sambaSID: S-1-1-11-1111111-111111111-11111111-324700
AWKが数学を実行し、結果の値を正しく配置できるため、これを達成するためにAWKを再利用できると思いました。数学部分を直接取り、変数に保存しました。
variable1=`awk -F ': ' '/uidNumber:/ { new = $2 * 2 + 1000; print new }' infile`
その後、同じファイル内の他のコマンドでこの変数を使用して置換を実行できます。
awk -F '-' -v variable2=$variable1 '/pattern of string 3 / { print $1"-"$2"-"$3"-"$4"-"$5"-"$6"-"$7"-"variable2 }'
文字列3データは、ダッシュ「-」で区切られた長い文字列であることに注意する必要があります。最後のダッシュの後に計算された値を配置する必要があります。
これはすべて機能しますが、1つの重要な欠陥があります。ファイルにレコードが1つある場合にのみ機能します。誰かが私にこれを行う方法についてのヒントを与えることができますか?
答え1
match()
この機能は以下で利用できますawk
。
$ cat file
somedata45
somedata47
somedata67
somedata53
somedata23
somedata12
awk '
BEGIN { RS = ""; OFS = "\n"; ORS = "\n\n" }
match($2, /[0-9]+/) { value = (substr($2, RSTART, RLENGTH) + 5) * 100 }
match($3, /[0-9]+/) { $3 = substr($2, 1, RSTART - 1) value }1' file
somedata45
somedata47
somedata5200
somedata53
somedata23
somedata2800
レコード区切り記号を空白に設定して、短絡モード(空白行区切り)を有効に有効にしました。各段落の2行目は私たちのものになり$2
、3行目は$3などになります。出力フィールド区切り文字を改行文字に設定しました。短絡モードのため、出力レコード区切り文字も2つの改行に設定しました。出力は最後に追加の改行を提供します。
このmatch()
関数を使用して数字の始まりを識別します。一致が見つかると、関数は2つの変数を入力し、一致がRSTART
開始RLENGTH
された時期と期間を示します。これらの変数を使用して計算を実行し、結果を変数に保存しますvalue
。このsubstr
機能を使用して数字を見つけます。
同じことを繰り返します$3
。今回は、substr
数字の先頭を印刷し、数値部分を前の行で計算された値を含む変数に置き換える関数を使用します。
参考にしてください文字列関数詳細については、ユーザーガイドを参照してください。
実際のデータに基づいて更新されました。
実際のデータは実際に仕事をはるかに単純にします。
awk '
/^uidNumber/ { value = $NF }
/^sambaSID/ {
n = split ($NF, tmp, /-/)
tmp[n] = ((value + 2)* 100)
for (i=1; i<=n; i++) { nf = (nf ? nf "-" tmp[i] : tmp[i]) }
$NF = nf
nf = ""
}1' file
dn: uid=NAME02, ou=data01, dc=data02, dc=data03
uidNumber: 3423
sambaSID: S-1-1-11-1111111-111111111-11111111-342500
dn: uid=NAME03, ou=data01, dc=data02, dc=data03
uidNumber: 3245
sambaSID: S-1-1-11-1111111-111111111-11111111-324700
uidNumber
最後のフィールドを含む行を見つけてキャプチャします。線が表示されたら、sambaSID
最後のフィールドを分割し-
、最後の要素を新しく計算された値に変更します。次にfor loop
a を使用して最後のフィールドを再グループ化します。
答え2
awkスクリプトでこれを行う方法は、行数を計算するためにいくつかの変数を保持することです。単一のスクリプトでこれを行うことができます。
/^[ \t]*$/ { lineCnt = 0; continue } # this matches blank lines and resets the count
{ lineCnt++ }
lineCnt == 2 { ... strip off your numeric ... }
lineCnt == 3 { ... do whatever you need to with the math ... }
2行目と3行目のブロックの末尾に「continue」ステートメントを追加すると、操作が完了したことがわかり、少し効率的になります。
答え3
awk
互いの変数値を使用して複数のパターンアクション式を結合する方法を尋ねているようです。たとえば、とても簡単です。
awk '/pattern2/ { calculate and assign var }; /pattern3/ {do something with var}'
この場合、必ずしも;
必要ではありませんが、理解するのに役立ちます。 1行スクリプトではなくawkスクリプトでは、式を改行で区切ることができます。
たとえば、file
次のような場合
pattern1
pattern2 3 5
pattern3
それから
$ awk '/pattern2/ {var = $2+$3}; /pattern3/ {print; print var}' file
pattern3
8
また、awkの組み込み関数OFS
(出力フィールド区切り記号) 変数を使用すると、出力形式をより簡単に指定できます。
pattern1
pattern2-3-5
pattern3-4-6
それから
$ awk -F- '/pattern2/ {var = $2+$3}; /pattern3/ {OFS="-"; print $1,$2,$3,var}' file
pattern3-4-6-8