
Tengo un nombre de archivo siguiendo este modelo:
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg
Necesito usar el cut
comando en Unix y cortar la cadena anterior para obtener 211
y 222
de las cadenas y hacer eco del valor.
Ya usé grep grep -o -E '[0-9]+'
, necesito una alternativa a esto.
Respuesta1
Sería mejor que utilizaras una herramienta de procesamiento de texto estándar en lugar de una herramienta ingenua como cut
.
A continuación se muestran algunas formas:
Con awk
, obteniendo el penúltimo campo _
o separado:.
awk -F '[_.]' '{print $(NF-1)}' file.txt
grep
con PCRE ( -P
):
grep -Po '\d+(?=[^_]*$)' file.txt
-o
solo recibe la porción igualada\d+
coincide con uno o más dígitosLa anticipación positiva de ancho cero,
(?=[^_]*$)
garantiza que no_
haya ningún seguimiento hasta el final de la línea.
Con sed
:
sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
.*_
coincide con todo hasta el final_
([[:digit:]]+)
coincide con los dígitos requeridos y se coloca en el grupo capturado.*
coincide con el restoEn el reemplazo, solo
\1
se utiliza el grupo capturado, .
Con perl
su misma lógica a la sed
de:
perl -pe 's/.*_(\d+).*/$1/' file.txt
Si debe usar cut
, hágalo en dos pasos, primero obtenga el _
cuarto campo separado y luego separe .
el primer campo:
cut -d_ -f4 file.txt | cut -d. -f1
Esto no se recomienda ya que requiere que los números de campo estén codificados.
Si fuera una cadena, lo haría usando la expansión de parámetros de Shell:
% str='1.raw_bank_details_211.trg'
% str=${str##*_}
% echo "${str%%.*}"
211
Todavía puedes usar una while
construcción y tomar cada línea en una variable y hacer esto, pero eso sería lento para un archivo grande. También puede utilizar _.
como alternativa IFS
y obtener el campo codificado (como cut
) si lo desea.
Ejemplo:
% cat file.txt
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg
% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222
% grep -Po '\d+(?=[^_]*$)' file.txt
211
222
% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222
% perl -pe 's/.*_(\d+).*/$1/' file.txt
211
222
% cut -d_ -f4 file.txt | cut -d. -f1
211
222
Respuesta2
cut
es la herramienta equivocada para eso. Para manipular cadenas cortas, como nombres de archivos, utilice las funciones de manipulación de cadenas del shell siempre que sea posible. Todos los shells de tipo sh¹ (sh, dash, bash, ksh, zsh,…) tienen cierta manipulación básica de cadenas como parte de la sustitución de variables. Véase, por ejemplo, elmanual del tableroen “expansión de parámetros”. Puede eliminar el prefijo/sufijo más corto/largo que coincida con un patrón.
Quiere la última secuencia de dígitos en el nombre del archivo, entonces:
- Determine el sufijo no numérico eliminando todo hasta el último dígito.
- Elimina ese sufijo.
- Quite todo hasta el último no dígito.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"
¹ Excepto algunos shells Bourne anteriores a POSIX, pero no te importan.