Saltar al contenido

¿Cómo pasar una expresión regular al encontrar una ruta de directorio en bash?

Solución:

Esto es sorprendentemente complicado de hacer bien.

Fundamentalmente, -d solo probará un único argumento, incluso si pudiera hacer coincidir los nombres de archivo usando una expresión regular.

Una forma sería darle la vuelta al problema y probar los directorios para una coincidencia de expresiones regulares en lugar de probar la coincidencia de expresiones regulares para los directorios. En otras palabras, haz un bucle todos los directorios en $HOME usando un simple globo de shell, y pruebe cada uno contra su expresión regular, rompiendo en una coincidencia, finalmente probando si el BASH_REMATCH la matriz no está vacía:

#!/bin/bash

for d in "$HOME"/*/; do
  if [[ $d =~ (ana|mini)conda[0-9]? ]]; then
    break;
  fi
done

if ((${#BASH_REMATCH[@]} > 0)); then
    echo "anaconda/miniconda directory is found in your $HOME"
  else
    echo "anaconda/miniconda is not found in your $HOME"
fi

Una forma alternativa sería usar un glob de shell extendido en lugar de la expresión regular y capturar cualquier coincidencia de glob en una matriz. Luego pruebe si la matriz no está vacía:

#!/bin/bash

shopt -s extglob nullglob

dirs=( "$HOME"/@(ana|mini)conda?([0-9])/ )

if (( ${#dirs[@]} > 0 )); then
  echo "anaconda/miniconda directory is found in your $HOME"
else
  echo "anaconda/miniconda is not found in your $HOME"
fi

El final / asegura que solo los directorios coincidan; los nullglob evita que el shell devuelva la cadena no coincidente en el caso de cero coincidencias.


Para hacer recursivo, establezca el globstar opción de shell (shopt -s globstar) y luego respectivamente: –

  • (versión de expresiones regulares): for d in "$HOME"/**/; do

  • (versión glob extendida): dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )

De hecho, como ya se mencionó, esto es complicado. Mi enfoque es el siguiente:

  • usar find y es regex capacidades para encontrar los directorios en cuestión.
  • dejar find imprimir un x para cada directorio encontrado
  • almacenar el xes en una cadena
  • si la cadena no está vacía, entonces se encontró uno de los directorios.

Por lo tanto:

xString=$(find $HOME -maxdepth 1 
                     -type d 
                     -regextype egrep 
                     -regex "$HOME/(ana|mini)conda[0-9]?" 
                     -printf 'x');
if [ -n "$xString" ]; then
    echo "found one of the directories";
else
    echo "no match.";
fi

Explicación:

  • find $HOME -maxdepth 1 encuentra todo debajo $HOME
    pero restringe la búsqueda a un nivel (es decir: no recurre a subdirectorios).
  • -type d restringe la búsqueda a solo directorios
  • -regextype egrep dice find que tipo de expresión regular nos ocupamos de. Esto es necesario porque cosas como [0-9]? y (…|…) son algo especiales y find
    no los reconoce por defecto.
  • -regex "$HOME/(ana|mini)conda[0-9]?" es el real
    expresión regular queremos estar atentos
  • -printf 'x' solo imprime un x para cada cosa
    que cumpla las condiciones anteriores.

Puede recorrer una lista de nombres de directorio que desea probar y actuar en consecuencia si existe uno de ellos:

a=0
for i in {ana,mini}conda{,2}; do
  if [ -d "$i" ]; then
    unset a
    break
  fi
done
echo "anaconda/miniconda directory is ${a+not }found in your $HOME"

Obviamente, esta solución no permite la potencia completa de expresiones regulares, pero la expansión de shell globbing y brace es igual al menos en el caso que mostró. El bucle sale tan pronto como existe un directorio y desarma la variable configurada previamente a. En el siguiente echo línea, la expansión del parámetro ${a+not } se expande a la nada si a está establecido (= no se encontró ningún directorio) y “no” más.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *