¿Cómo probar si existe una cadena en el archivo con Bash?

Resuelto Toren asked hace 13 años • 16 respuestas

Tengo un archivo que contiene nombres de directorio:

my_list.txt:

/tmp
/var/tmp

Me gustaría registrar Bash antes de agregar un nombre de directorio si ese nombre ya existe en el archivo.

Toren avatar Jan 20 '11 22:01 Toren
Aceptado
grep -Fxq "$FILENAME" my_list.txt

El estado de salida es 0 (verdadero) si se encontró el nombre, 1 (falso) en caso contrario, entonces:

if grep -Fxq "$FILENAME" my_list.txt
then
    # code if found
else
    # code if not found
fi

Explicación

Aquí están las secciones relevantes de la página de manual paragrep :

grep [options] PATTERN [FILE...]

-F,--fixed-strings

        Interprete PATRÓN como una lista de cadenas fijas, separadas por nuevas líneas, cualquiera de las cuales debe coincidir.

-x,--line-regexp

        Seleccione sólo aquellas coincidencias que coincidan exactamente con toda la línea.

-q, --quiet,--silent

        Tranquilo; no escriba nada en la salida estándar. Salga inmediatamente con estado cero si se encuentra alguna coincidencia, incluso si se detectó un error. Consulte también la opción -so --no-messages.

Manejo de errores

Como se señaló correctamente en los comentarios, el enfoque anterior trata silenciosamente los casos de error como si se encontrara la cadena. Si desea manejar los errores de una manera diferente, deberá omitir la -qopción y detectar errores según el estado de salida:

Normalmente, el estado de salida es 0 si se encuentran las líneas seleccionadas y 1 en caso contrario. Pero el estado de salida es 2 si ocurrió un error, a menos que se use la opción -qo y se encuentre una línea seleccionada. Tenga en cuenta, sin embargo, que POSIX sólo exige, para programas como , y , que el estado de salida en caso de error sea mayor que 1; Por lo tanto, es aconsejable, en aras de la portabilidad, utilizar una lógica que pruebe esta condición general en lugar de una igualdad estricta con 2.--quiet--silentgrepcmpdiff

Para suprimir la salida normal de grep, puede redirigirla a /dev/null. Tenga en cuenta que el error estándar no está dirigido, por lo que cualquier mensaje de error que greppueda imprimirse terminará en la consola como probablemente desee.

Para manejar los tres casos, podemos usar una casedeclaración:

case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
  0)
    # code if found
    ;;
  1)
    # code if not found
    ;;
  *)
    # code if an error occurred
    ;;
esac
Thomas avatar Jan 20 '2011 15:01 Thomas

Respecto a la siguiente solución:

grep -Fxq "$FILENAME" my_list.txt

En caso de que te preguntes (como yo) qué -Fxqsignifica en inglés sencillo:

  • F: Afecta cómo se interpreta PATTERN (cadena fija en lugar de una expresión regular)
  • x: Coincidir con toda la línea
  • q: Shhhhh... impresión mínima

Del archivo man:

-F, --fixed-strings
    Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of which is to be matched.
    (-F is specified by POSIX.)
-x, --line-regexp
    Select only those matches that exactly match the whole line.  (-x is specified by POSIX.)
-q, --quiet, --silent
    Quiet; do not write anything to standard output.  Exit immediately with zero status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages option.  (-q is specified by
          POSIX.)
Kuf avatar Jan 07 '2013 18:01 Kuf

Tres métodos en mi mente:

1) Prueba breve para un nombre en una ruta (no estoy seguro de que este sea su caso)

ls -a "path" | grep "name"


2) Prueba breve para una cadena en un archivo

grep -R "string" "filepath"


3) Script bash más largo que usa expresiones regulares:

#!/bin/bash

declare file="content.txt"
declare regex="\s+string\s+"

declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
    then
        echo "found"
    else
        echo "not found"
fi

exit

Esto debería ser más rápido si tiene que probar varias cadenas en el contenido de un archivo usando un bucle, por ejemplo, cambiando la expresión regular en cualquier ciclo.

Luca Borrione avatar Nov 02 '2012 10:11 Luca Borrione

La forma más fácil y sencilla sería:

isInFile=$(cat file.txt | grep -c "string")


if [ $isInFile -eq 0 ]; then
   #string not contained in file
else
   #string is in file at least once
fi

grep -c devolverá el recuento de cuántas veces aparece la cadena en el archivo.

Christian737 avatar Oct 06 '2017 10:10 Christian737