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 -l
no 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 -n
simplemente 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 '^' 2
fuente
WHITESPACE_ONE=' '
en mi shell (bash) todavía funciona, informando correctamente una línea.printf
lugar 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
$var
resultará 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
?var
contiene una línea : no interpretaste el\n
con nada. Pon varias líneas en tuvar
y 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 -l
soluciones salidas 1 incluso si la variable de entrada está vacía, porwc -w
lo 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 -f
es necesario para evitar una expansión glob no deseada. Intente utilizar el método 2 envar=$'*\n.*'
.wc -l
Una 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 "^" 2
fuente
echo
(comoecho -n
) no es estándar y puede dar resultados diferentes en diferentes implementaciones. Considerando queprintf
hace lo que queremos por defecto. Como beneficio adicional, el uso leprintf
ahorra un proceso, ya que es un shell integrado. (Sugerencia:printf "$a" | wc -l
es 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
,%d
y así on ... Lo mismo si la cadena comienza con un guión. En cambio, el parámetro 2 enprintf
se 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
1
Wiggum 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 (
-z
como 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