
tengo un archivo
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
Ahora, en toda la fila, cuando encuentro "R" && luego "O" o "S", quiero obtener el número de columna y, según el número de columna, necesito ejecutar un comando y, si es verdadero, mostrar L en lugar de R y O. o S si es falso, entonces F en lugar de R y F en lugar de O (para todas las O consecutivas) o S
ahora de la columna no determinaré la fecha,
digamos que para la primera fila R está en 5, por lo que la fecha será la columna número 3, es decir, la segunda,
para la segunda fila la fecha será 6-3, es decir, la tercera, la tercera fila nuevamente 5-3, es decir, la segunda,
Entonces usaré una variable fecha=%m/d(de la columna no-3)/%Y
ahora el comando es ./bpimagelist -client <column 1> -policy <column 2> -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l
, ahora si el valor es 0 entonces es falso si es gt 0 entonces es verdadero.
XYZ is false
PQR is true
ABC is true
entonces la salida debería ser
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
Según Valentin, después de realizar algunos cambios, este es el código que parece funcionar bien.
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
Sin embargo, una pequeña consulta es que debería realizar estos cambios solo cuando R va seguido de O y hasta que encuentre algo menos O.
lo que significa que no debería realizar ningún cambio si el archivo de entrada es como
XYZ 123 S S R O O O O
lo que significa que R continúa solo con O, por lo que no es necesario realizar ningún cambio; de lo contrario, se encuentra cualquier cosa que no sea O, realice los cambios
Respuesta1
Intentaré responder a tu solicitud paso a paso. Simplemente asuma aquí que input
es una línea de su archivo de entrada:
Extrayendo el número de columna del primer carácter "R"
Este es un trabajo bastante sencillo para awk
:
awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 3; exit} } }' < input
Teniendo en cuenta cómo calcula su fecha, supongo que la 'R' no puede estar en la primera fila (de lo contrario, el número del día podría ser 0).
Extracción de valores de la 1.ª y 2.ª columna.
Esto es aún más sencillo:
awk '{print $1}' < input # for first column
awk '{print $2}' < input # for second column
Construyendo salida
En caso de que el comando devuelva True
:
sed 's/ R / L /' < input
En caso de que el comando devuelva 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
Poniendolo todo junto
Aunque esto está mal visto, no veo forma de evitar recorrer las líneas de entrada, ya que necesita ejecutar un comando muy específico para cada línea. Tenga en cuenta que, para archivos grandes, esto puede resultar muy lento. Cómo podría verse tu guión con todos estos elementos:
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