
ファイルがあります
XYZ 123 S S R O O S F
PQR 456 F S S R O F F
ABC 789 F S R S S F S
行全体で「R」と「O」または「S」が見つかったら、列番号を取得し、列番号に基づいてコマンドを実行する必要があります。これが true の場合は、R と O または S の代わりに L を表示し、false の場合は、R の代わりに F を、O (連続するすべての O) の代わりに F または S を表示します。
今、列番号から日付を決定します、
1行目のRが5だとすると、日付は列番号3、つまり2番目になります。
2行目の日付は6-3、つまり3番目、3行目は再び5-3、つまり2番目、
そこで、変数date=%m/d(列番号3から)/%Yを使用します。
コマンドは です./bpimagelist -client <column 1> -policy <column 2> -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l
。値が 0 の場合は false、0 の場合は true になります。
XYZ is false
PQR is true
ABC is true
出力は次のようになります
XYZ 123 S S F F F S F
PQR 456 F S S L O F F
ABC 789 F S L S S F S
Valentin によると、いくつかの変更を加えた後、このコードは正常に動作するようです。
while read line;
do
day="$(echo $line | awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 2; exit} } }')"
if [[ ${#day} -lt 2 ]]; then day="0${day}"; fi
month=`date '+%m'`
year=`date '+%Y'`
date=`echo $month/$day/$year`
result=$(sudo /usr/openv/netbackup/bin/admincmd/bpimagelist -client "$(echo $line | awk '{print $1}')" -policy "$(echo $line | awk '{print $2}')" -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l)
if [[ $result -ne 0 ]];
then
echo $line | sed 's/ R / L /'
else
echo $line | awk '{
afterR=0;
for (i=1; i<=NF; i++){
if ($i == "R") {
$i = "F";
afterR=1;
}
if (afterR == 1 && $i == "O") {
$i = "F"
}
}
print $0
}'
fi
done < temp
ただし、1 つの小さな疑問は、R の後に O が続く場合にのみ、そして O 以外のものが見つかるまで、これらの変更を実行する必要があることです。
つまり、入力ファイルが次のような場合は変更を行わないということです。
XYZ 123 S S R O O O O
つまり、RはOのみで継続されるため、変更を行う必要はありません。O以外のものが見つかった場合は変更を実行します。
答え1
あなたのリクエストに段階的に答えてみます。ここではinput
入力ファイルの行を想定します:
最初の「R」文字の列番号を抽出します
これは、次の人にとっては非常に簡単な仕事ですawk
。
awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 3; exit} } }' < input
日付を計算する方法を考慮すると、「R」は最初の行にはないと考えられます (そうでない場合、日付の数字は 0 になる可能性があります)。
1列目と2列目の値の抽出
これはさらに簡単です:
awk '{print $1}' < input # for first column
awk '{print $2}' < input # for second column
出力の構築
コマンドが返される場合True
:
sed 's/ R / L /' < input
コマンドが返される場合False
:
awk '{
afterR=0;
for (i=1; i<=NF; i++){
if ($i == "R") {
$i = "F";
afterR=1;
}
if (afterR == 1 && $i == "O") {
$i = "F"
}
}
print $0
}' < input
すべてを一緒に入れて
これは好ましくないことですが、各行に非常に具体的なコマンドを実行する必要があるため、入力行をループすることを避ける方法はないと思います。大きなファイルの場合、これは非常に遅くなる可能性があることに注意してください。これらの要素をすべて含めたスクリプトは次のようになります。
while read line;
do
date="%m/d$(echo $line | awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 3; exit} } }')/%Y"
result=$(./bpimagelist -client "$(echo $line | awk '{print $1}')" -policy "$(echo $line | awk '{print $2}')" -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l)
if [[ $result -ne 0 ]];
then
echo $line | sed 's/ R / L /'
else
echo $line | awk '{
afterR=0;
for (i=1; i<=NF; i++){
if ($i == "R") {
$i = "F";
afterR=1;
}
if (afterR == 1 && $i == "O") {
$i = "F"
}
}
print $0
}'
fi
done < myinputfile.txt