awkによって検出された各オカレンスを配列に格納します
私の前の質問には「重複」のフラグが付けられ、これとこれが指摘されました。それらのスレッドで提供されるソリューションは、これをまったく解決しません。
file.txtの内容:
Some line of text 0
Some line of text 1
Some line of text 2
PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2
Some line of text 6
Some line of text 7
Some line of text 8
PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2
Some line of text 12
Some line of text 13
Some line of text 14
「PATTERN1」と「PATTERN2」+の間に行を抽出する必要があり、次のコマンドはこれを完全に実行します。
awk '/ PATTERN1 /、/ PATTERN2 /'./file.txt
出力:
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2 PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
しかし今、私は次のようなbashスクリプトを作成しようとしています。
- awkを使用してPATTERN1とPATTERN2の間の行を検索します
- PATTERN1 +行の間にある各行+ PATTERN2を配列に格納します
- ファイルの終わりまで1と2を実行します。
明確にするために。引用符の中に次の行を格納することを意味します。
"PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2"
に array[0]
次の行を引用符で囲みます。
"PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2"
に array[1]
など..... PATTERN1とPATTERN2の出現が多い場合
私が現在持っているもの:
#!/bin/bash
var0=`cat ./file.txt`
mapfile -t thearray < <(echo "$var0" | awk '/PATTERN1 /,/PATTERN2/')
上記は機能しません。
また、スクリプトがサポートされていないシステムで実行される可能性があるため、可能な限りmapfileを使用したくありません。
提供されたこのリンクに基づく:
myvar=$(cat ./file.txt)
myarray=($(echo "$var0" | awk '/PATTERN1 /,/PATTERN2/'))
しかし、私がするとき echo ${myarray[1]}
空白の応答があります。
そして私がするとき echo ${myarray[0]}
私は得る:
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2 PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
エコーするときに期待すること ${myarray[0]}
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2
私がするときに私が期待すること echo ${myarray[1]}
PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
どんな助けでも素晴らしいでしょう。
回答
チャールズが提案...
ブロックの改行を削除するように編集されました(すべてのレコードではありません)
while IFS= read -r -d '' x; do array+=("$x"); done < <(awk ' /PATTERN1/,/PATTERN2/ { if ( $0 ~ "PATTERN2" ) { x=$0; printf "%s%c",x,0; next }
print }' ./file.txt)
再フォーマットしました。ちょっと忙しくて読みづらくなっていました。
そしてそれをテストするには-
$: echo "[${array[1]}]"
[PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2]
余談ですが、データ要素に冗長な番兵の値を含めるのは非常に奇妙に思えます。したがって、それらを削除したい場合は、次のようにします。
$: while IFS= read -r -d '' x; do array+=("$x"); done < <( awk '/PATTERN1/,/PATTERN2/{ if ( $0 ~ "PATTERN1" ) { next }
if ( $0 ~ "PATTERN2" ) { len--; for (l in ary) { printf "%s%c", ary[l], l<len ? "\n" : 0; } delete ary; len=0; next } ary[len++]=$0;
}' ./file.txt )
$: echo "[${array[1]}]"
[Some line of text 9
Some line of text 10
Some line of text 11]
プレーンでの実装はbash
次のようになります。
#!/bin/bash
beginpat='PATTERN1'
endpat='PATTERN2'
array=()
n=-1
inpatterns=
while read -r; do
if [[ ! $inpatterns && $REPLY = $beginpat ]]; then array[++n]=$REPLY
inpatterns=1
elif [[ $inpatterns ]]; then array[n]+=$'\n'$REPLY if [[ $REPLY = $endpat ]]; then inpatterns= fi fi done # Report captured lines for ((i = 0; i <= n; ++i)); do printf "=== array[%d] ===\n%s\n\n" $i "${array[i]}"
done
として実行し./script < file
ます。の使用awk
は必須ではありませんが、スクリプトはawk
出力でも正しく機能します。
ポールの答えは私が望むことをするので、私はそれを受け入れられた答えとしてフラグを立てました。彼のソリューションでは、配列に格納されているすべての値の下部に空白の余分な行が生成されますが、これは問題ありませんが、とにかく簡単に削除できるので、気にしませんでした。しかし、私はこの同じ質問を別のサイトにも投稿しました。ポールの答えは良かったのですが、より良い解決策を見つけました。
IFS=$'\r' read -d'\r' -a ARR < <(awk '/PATTERN1/,/PATTERN2/ {if($0 ~ /PATTERN2/) printf $0"\r"; else print}' file.txt)
上記は仕事をし、空白の余分な行を生成せず、その1つのライナーです。
echo "${ARR[1]}"
echo "${ARR[0]}"
出力:
PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2
PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2