
Tengo una variable asignada a una cadena devuelta:
ytd_wk=$(cat file.csv | grep $(date +'%Y') | tail -1)
Quiero subcadenar los últimos 2 caracteres:
ytd_wk=${ytd_wk:(-2)}
¿Hay alguna forma de utilizar una sola línea para lograr esto? Lo intenté a continuación pero obtuve bad substitution
un error:
ytd_wk=${$(cat file.csv | grep $(date +'%Y') | tail -1):(-2)}
Respuesta1
Tratar de usar:
grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/'
No es necesario cat
porque grep
puede obtener datos tanto de la salida de otro programa como de un archivo determinado. El último método es más eficiente porque utiliza un solo comando y este es más rápido y consume menos recursos del sistema.
La solución completa:
ytd_wk=$(grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/')
Puedes omitir tail
con GNU sed '$!d'
:
grep "$(date +'%Y')" file.csv | sed -r '$!d;s/.*(..$)/\1/'
POSIX:
grep "$(date +'%Y')" file.csv | sed -e '$!d' -e 's/.*\(..$\)/\1/'
Respuesta2
Podrías usar awk
, combinando cat
, grep
, sed
y tail
otras sugerencias:
awk -v year=$(date +'%Y') '$0 ~ year {line=$0} END {print substr(line,length(line)-1,2)}' file.csv
Escribiendo esto paso a paso
-v year=$(date +'%Y')
establece laawk
variableyear
al año actual$0 ~ year { line=$0 }
esto se aplica a cada línea del archivo por turno. Si hay una coincidencia con el año en la línea actual, la guarda en laawk
variableline
END { print substr(line,length(line)-1,2) }
al final del archivo (después de que se haya leído y procesado la última línea), se imprimen los dos últimos caracteres de la línea guardada más recientemente. Imprime una línea en blanco si no hubo ninguna coincidencia exitosa anteriormente.
Respuesta3
Esto es más eficiente, especialmente siarchivo.csves grande y la línea deseada está más cerca del final:
ytd_wk="$(tac file.csv | grep -m 1 $(date +'%Y') | grep -o '..$')"
Cómo funciona: tac
salidasarchivo.csvhacia atrás y grep -m 1
encuentra la primera instancia del patrón, que se alimenta y grep -o
genera solo los dos últimos caracteres.