web-dev-qa-db-de.com

Wie zähle ich in Bash die Anzahl der Zeilen in einer Variablen?

ich habe eine var, die eine Zeichenfolge enthält, und muss überprüfen, ob es Zeilen enthält:

var=`ls "$sdir" | grep "$input"`

pseudocode:

while [ ! $var's number of lines -eq 1 ]
  do something

das ist meine Idee, wie zu überprüfen ist, echo $var | wc -l funktioniert nicht, es sagt immer 1, obwohl es 3 hat

echo -e funktioniert nicht

49
krack krackerz

Zitate sind wichtig.

echo "$var" | wc -l

Die akzeptierte Antwort und andere hier veröffentlichte Antworten funktionieren nicht bei einer leeren Variablen (undefinierter oder leerer String).

Das funktioniert:

echo -n "$VARIABLE" | grep -c '^'

Zum Beispiel:

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
44
Julian

Eine andere Möglichkeit mit hier Strings in der Bash:

wc -l <<< "$var"

Wie in diesem Kommentar erwähnt, ergibt ein leerer $var eine Zeile anstelle von 0 Zeilen, da here Zeichenfolgen in diesem Fall ein Zeilenvorschubzeichen ( Erklärung ) hinzufügen.

19
speakr

Sie können "wc -l" durch "wc -w" ersetzen, um die Anzahl der Wörter statt der Zeilen zu zählen. Dadurch werden keine neuen Zeilen gezählt und Sie können verwenden, um zu testen, ob Ihre ursprünglichen Ergebnisse leer sind, bevor Sie fortfahren.

Die am besten bewerteten Antworten schlagen fehl, wenn keine Ergebnisse von einem Grep zurückgegeben wurden.

Homer Simpson
Marge Simpson
Bart Simpson
Lisa Simpson
Ned Flanders
Rod Flanders
Todd Flanders
Moe Szyslak

Dies ist der falsche Weg, es zu tun :

wiggums=$(grep -iF "Wiggum" characters.txt);
num_wiggums=$(echo "$wiggums" | wc -l);
echo "There are ${num_wiggums} here!";

Es wird uns sagen, dass 1Wiggum in der Liste ist, auch wenn es keine gibt.

Stattdessen müssen Sie eine zusätzliche Prüfung durchführen, um zu sehen, ob die Variable leer ist (-z, da in "ist Null"). Wenn grep nichts zurückgibt, ist die Variable leer.

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";
3

Niemand hat die Parametererweiterung erwähnt, daher gibt es ein paar Möglichkeiten, pure bash zu verwenden.

Methode 1

Entfernen Sie Nicht-Zeilenvorschubzeichen, und erhalten Sie die Zeichenfolgenlänge + 1. Anführungszeichen sind wichtig.

 var="${var//[!$'\n']/}"
 echo $((${#var} + 1))

Methode 2

In Array konvertieren, dann Arraylänge abrufen. Damit dies funktioniert, verwenden Sie keine Anführungszeichen.

 var=(${var})
 echo ${#var[@]}
1
haqk

Eine einfachere Version von @Julians Antwort, die für alle Zeichenfolgen funktioniert, mit oder ohne nachlaufende\n (sie zählt eine Datei, die nur eine einzelne nachlaufende\n als leer enthält)

printf "%s" "$a" | grep -c "^"

  • Gibt null zurück: unset variable, leere Zeichenfolge, Zeichenfolge, die eine leere Zeile enthält
  • Gibt 1 zurück: jede nicht leere Zeile, mit oder ohne Zeilenumbruch
  • usw

Ausgabe:

# 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
0
Stilez