Powiedzmy, że mam dwie zmienne w bash:
MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
Chcę wykryć, kiedy zmienna faktycznie zawiera więcej niż jeden wiersz tekstu, pomijając dodatkowe znaki nowego wiersza.
Więc to:
if [ some test on "$MULTILINE" ]; then echo 'yes'; else echo 'no'; fi
wydrukuje yes
, a to:
if [ some test on "$SINGLE_LINE" ]; then echo 'yes'; else echo 'no'; fi
wydrukuje no
.
W moim konkretnym przypadku nie sądzę, żebym musiał martwić się prowadzeniem pustych linii, ale nie zaszkodzi wiedzieć, jak to zrobić.
W jaki sposób mogę to zrobić?
Odpowiedzi:
Najprostsze rozwiązanie, jakie znam:
na przykład:
==>
Powyższe ignoruje wszystkie puste linie: wiodące, końcowe i wewnętrzne. Należy jednak pamiętać, że nie można mieć wewnętrznej pustej linii, chyba że istnieją co najmniej dwie niepuste linie, więc jej istnienie nie może zmienić pytania, czy po przycięciu początkowych i końcowych pustych linii jest więcej niż jedna linia.
źródło
Zobacz /programming/16414410/delete-empty-lines-using-sed,
aby uzyskać więcej informacji na temat przycinania / usuwania białych znaków i pustych linii za pomocą sed.
Teraz napisz swoje
if expression ...
użycie$( ... )
w cudzysłowie, aby uzyskać liczbę wierszy i przetestować względem liczby:źródło
Powinna to zrobić niewielka modyfikacja tego kodu . Możesz umieścić go we własnym skrypcie do ponownego użycia w następujący sposób:
Następnie możesz użyć go w ten sposób (zakładając, że nazwałeś poprzedni skrypt
multiline-check.sh
):źródło
fi
. Niestety utknąłem na bash 3.1 (wersja msysgit). Nie widzę niczego, co wygląda jak błąd składniowy, ale oczywiście coś mi brakuje. Myśli?Ignorowanie końcowych pustych linii
Oto podejście wykorzystujące
awk
:Jak to działa:
echo „$ TEST”
Pobiera każdą zmienną powłoki, którą jesteśmy zainteresowani i wysyła ją do standardowego wyjścia.
tac
To odwraca kolejność linii, tak że ostatnia linia jest zwracana jako pierwsza. Po wykonaniu
tac
linie końcowe stają się liniami wiodącymi.(Nazwa
tac
jest odwrotnacat
do powodu, którytac
robi to, cocat
robi, ale odwrotnie).awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }'
Przechowuje numer pierwszej niepustej linii w zmiennej
f
. Po przeczytaniu wszystkich liniach, porównujef
się do całkowitej liczby liniiNR
. jeślif
jest równeNR
, to mieliśmy tylko jedną linię (ignorując początkowe puste miejsca) i wychodzimy z kodem 0. Jeśli po pierwszej pustej linii była jedna lub więcej linii, to kończy się kodem `.&& echo "Found A Single Line"
W przypadku
awk
wyjścia z kodem 0,echo
instrukcja jest wykonywana.Ignorowanie zarówno wiodących, jak i końcowych pustych linii
Tworząc jedną dodatkową
awk
zmienną, możemy rozszerzyć test o ignorowanie zarówno początkowych, jak i końcowych pustych linii:Ponieważ ta wersja
awk
kodu obsługuje zarówno początkowe, jak i końcowe spacje,tac
nie jest już potrzebna.Jednoczesne przyjmowanie
awk
kodu:first==0 && /./ {first=NR}
Jeśli zmienna
first
ma wartość zero (lub nie została jeszcze ustawiona), a linia ma znak, dowolny znak, to ustawfirst
numer linii. Poawk
zakończeniu odczytu liniifirst
zostanie ustawiony na numer pierwszej niepustej linii././ {last=NR}
Jeśli linia ma jakiś znak, ustaw zmienną
last
na bieżący numer linii. Poawk
zakończeniu odczytu wszystkich linii zmienna będzie miała numer ostatniej niepustej linii.END{if(first==last){exit 0}; exit 1 }
Wykonuje się to po odczytaniu wszystkich wierszy. Jeśli
first
jest równylast
, to widzieliśmy zero lub wiersze niepustych linii iawk
wychodzi z kodem0
. W przeciwnym razie kończy się kodem1
. Skrypt powłoki może jak zwykle przetestować kod wyjścia za pomocąif
instrukcji lub&&
lub||
.źródło