Tengo una variable que tiene una cadena almacenada y necesito verificar si tiene líneas:
var=`ls "$sdir" | grep "$input"`
pseudocódigo:
while [ ! $var's number of lines -eq 1 ]
do something
Esa es mi idea sobre cómo comprobarlo. echo $var | wc -lno funciona - siempre dice 1, aunque lo ha hecho 3.
echo -e no funciona tan bien.

if [ -z "$var" ]; then printf '%s\n' '0'; else printf '%s\n' "${var%$'\n'}" | wc -l; fi. Pruebe convar=(sin líneas)var='foo'yvar=$'foo\n'(ambas una línea en el sentido * nix).LINE_COUNT=$(wc -l <<< "${var}")echo -nsimplemente disminuirá el recuento en uno. @lucifuriousecho $(wc -l <<< "${NONEXISTENTVAR}")todavía da 1, no 0La respuesta aceptada y otras respuestas publicadas aquí no funcionan en el caso de una variable vacía (cadena vacía o indefinida).
Esto funciona:
echo -n "$VARIABLE" | grep -c '^'Por ejemplo:
ZERO= ONE="just one line" TWO="first > second" echo -n "$ZERO" | grep -c '^' 0 echo -n "$ONE" | grep -c '^' 1 echo -n "$TWO" | grep -c '^' 2fuente
WHITESPACE_ONE=' 'en mi shell (bash) todavía funciona, informando correctamente una línea.printflugar deecho -n. Agregué esto como una respuesta alternativa, para incluir los resultados de las pruebas. Vea abajo.Otra forma de usar aquí cadenas en bash:
wc -l <<< "$var"Como se menciona en este comentario , un vacío
$varresultará en 1 línea en lugar de 0 líneas porque aquí las cadenas agregan un carácter de nueva línea en este caso ( explicación ).fuente
wc -l <<<"$(echo "$var")"(sí, todos los símbolos eran necesarios)$var?varcontiene una línea : no interpretaste el\ncon nada. Pon varias líneas en tuvary funcionará, por ejemplo, convar="foo<ENTER>bar<ENTER>baz"<ENTER>.xxd <<< ''crea este hexdump00000000: 0a. Por lo tanto,<<<(Here Strings) agrega un carácter de nueva línea a cualquier contenido.Puede sustituir "wc -l" por "wc -w" para contar el número de palabras en lugar de líneas. Esto no contará ninguna línea nueva y se puede usar para probar si los resultados originales están vacíos antes de continuar.
fuente
wc -lsoluciones salidas 1 incluso si la variable de entrada está vacía, porwc -wlo que será mejor usarla.Nadie ha mencionado la expansión de parámetros, así que aquí hay un par de formas de usar bash puro.
Método 1
Elimine los caracteres que no sean de nueva línea, luego obtenga la longitud de la cadena + 1. Las comillas son importantes .
var="${var//[!$'\n']/}" echo $((${#var} + 1))Método 2
Convierta a matriz, luego obtenga la longitud de la matriz. Para que esto funcione, no use comillas .
set -f # disable glob (wildcard) expansion IFS=$'\n' # let's make sure we split on newline chars var=(${var}) echo ${#var[@]}fuente
IFS. Así que configúreloIFS=$'\n'para asegurarse de que la variable se divida en nuevas líneas al expandirla en una matriz:IFS=$'\n'; var=(${var})set -fes necesario para evitar una expansión glob no deseada. Intente utilizar el método 2 envar=$'*\n.*'.wc -lUna versión más simple de la respuesta de @ Julian, que funciona para todas las cadenas, con o sin \ n final (sí cuenta un archivo que contiene solo un \ n final como vacío):
printf "%s" "$a" | grep -c "^"Salida:
# a= # printf "%s" "$a" | grep -c "^" 0 # a="" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf "")" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf "\n")" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf " \n")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf " ")" # printf "%s" "$a" | grep -c "^" 1 # a="aaa" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s" "aaa")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s\n" "aaa")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s\n%s" "aaa" "bbb")" # printf "%s" "$a" | grep -c "^" 2 # a="$(printf "%s\n%s\n" "aaa" "bbb")" # printf "%s" "$a" | grep -c "^" 2fuente
echo(comoecho -n) no es estándar y puede dar resultados diferentes en diferentes implementaciones. Considerando queprintfhace lo que queremos por defecto. Como beneficio adicional, el uso leprintfahorra un proceso, ya que es un shell integrado. (Sugerencia:printf "$a" | wc -les más conciso y evita el uso innecesario degrep)printf .... | wc -l, solo eliminará una línea adicional (la nueva línea) para que, en caso de una línea vacía, el resultado sea 0 . Correcto. Pero si pasamos 2 líneas, el resultado será 1, donde la misma variable pasada alprintf ... | grep "^"devolverá correctamente 2. Además, usar directamenteprintf "$a"es muy peligroso, porque puede llevar a errores silenciosos si la cadena contiene accidentalmente caracteres como%s,%dy así on ... Lo mismo si la cadena comienza con un guión. En cambio, el parámetro 2 enprintfse escapa automáticamenteLas respuestas más votadas fallan si un grep no devolvió resultados.
Esta es la forma incorrecta de hacerlo :
wiggums=$(grep -iF "Wiggum" characters.txt); num_wiggums=$(echo "$wiggums" | wc -l); echo "There are ${num_wiggums} here!";Allí nos dirá, hay
1Wiggum en la lista, incluso si no hay ninguno.En su lugar, debe hacer una verificación adicional para ver si la variable está vacía (
-zcomo en "es cero"). Si grep no devolvió nada, la variable estará vacía.matches=$(grep -iF "VanHouten" characters.txt); if [ -z "$matches" ]; then num_matches=0; else num_matches=$(echo "$matches" | wc -l); fi echo "There are ${num_matches} VanHoutens on the list";fuente
Otro método para contar el número de líneas en una variable, suponiendo que haya verificado que se completó correctamente o que no está vacío, para eso solo marque $? después de la afectación del resultado de subcapa var -:
readarray -t tab <<<"${var}" echo ${#tab[@]}readarray | mapfile es un comando interno de bash que convierte el archivo de entrada, o aquí cadena en este caso, en una matriz basada en nuevas líneas.
-t flag evita almacenar nuevas líneas al final de las celdas de la matriz, útil para el uso posterior de valores almacenados
Las ventajas de este método son:
fuente
Para evitar el nombre de archivo en el comando "wc -l":
lines=$(< "$filename" wc -l) echo "$lines"fuente