Usando bash tengo algo como:

MYLIST='Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp'

En realidad, la lista puede tener cientos de palabras diferentes en diferente orden. Solo trato de mantenerlo simple.

¿Cómo cambiaría la lista para excluir palabras que terminan con .xy.c?

Preferiría usar una expresión regular si es posible.

Gracias.

0
user3161924 27 ene. 2016 a las 02:17

3 respuestas

La mejor respuesta

Puede usar las reglas del patrón Bash como un lenguaje similar a una expresión regular. En particular, Bash da preferencia especial a $ @ y $ * al aplicar patrones; los trata como listas de palabras y aplica el patrón a cada elemento de la lista.

Como resultado, debe escribir una función (por lo que tendrá una lista de parámetros en $ @ o $ *) para que pueda aplicar el patrón sobre la lista. Utilizaría el patrón %%, que dice "emparejar y eliminar el patrón más largo posible". Esta es mi opinión al respecto:

$ strip_xy_cpp() {
>     RESULT="${*%%*.xy.cpp}"
>     echo "$RESULT"
> }

$ echo $MYLIST
Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp

$ NEWLIST=$( strip_xy_cpp $MYLIST )

$ echo $NEWLIST
Word1.c Word2.c Word3.xy.c Word4.cpp
2
aghast 26 ene. 2016 a las 23:50
$ my_list='Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp'
$ read -ra my_arr <<< "$my_list"
$ result_arr=()
$ for i in "${my_arr[@]}"; do [[ $i != *.xy.c ]] && result_arr+=("$i"); done
$ printf '%s\n' "${result_arr[@]}"
Word1.c
Word2.c
Word4.cpp
Word5.xy.cpp

Como nota al margen:

Por convención, las variables de entorno (PATH, EDITOR, SHELL, ...) y las variables de shell internas (BASH_VERSION, RANDOM, ...) son completamente en mayúsculas. Todos los demás nombres de variables deben estar en minúsculas. Ya que Los nombres de las variables distinguen entre mayúsculas y minúsculas, esta convención evita anular accidentalmente las variables ambientales e internas.

1
Rany Albeg Wein 27 ene. 2016 a las 00:06

Tengo una solución que no usa REGEX, pero al menos es un script simple:

Probé el guión:

str="Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp"
echo $str
for file in $str
do
    if [ ! ${file: -5} == ".xy.c" ]
    then
        echo $file
    fi
done

Esto se podría cambiar para incluir un parámetro:

for str in $1
do
    if [ ! ${str: -5} == ".xy.c" ]
    then
        echo $str
    fi
done
  • La sección for str in $1 recorre cada archivo (o palabra) separados por un espacio.
  • La sección ! ${str: -5} == ".xy.c" comprueba si los últimos cinco caracteres de la cadena str son iguales a .xy.c. Si son iguales, entonces la ! hace que la declaración if resulte falsa. Por lo tanto, esa cadena str en particular no se imprime con echo

Entonces podrías ejecutar:

$ bash scriptName.sh "Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp"

Y si desea almacenar la salida en un archivo:

$ bash scriptName.sh "Word1.c Word2.c Word3.xy.c Word4.cpp Word5.xy.cpp" > result.txt
1
Caleb Adams 26 ene. 2016 a las 23:45