파일이 있어요
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인 경우 대신 L을 표시해야 합니다. R 및 O 또는 S가 거짓인 경우 R을 F로 바꾸고 O를 F(모든 연속 O에 대해) 또는 S로 바꿉니다.
이제 "아니요" 열에서 날짜를 결정하겠습니다.
첫 번째 행 R이 5에 있다고 가정하면 날짜는 두 번째 열인 3열이 됩니다.
두 번째 행의 경우 날짜는 6-3, 즉 세 번째 행이 되고, 세 번째 행의 경우 날짜는 5-3, 즉 두 번째 행이 됩니다.
따라서 변수 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이고 gt 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
그러나 한 가지 작은 문제는 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이 될 수 있습니다).
첫 번째와 두 번째 열의 값을 추출합니다.
이것은 더 간단합니다:
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