Jeśli przypadkowo próbujesz poradzić sobie z cytatami dotyczącymi ponownego użycia powłoki, możesz to zrobić bez usuwania ich, a to również jest bardzo proste:
aq() { sh -c 'for a do
alias "$((i=$i+1))=$a"
done; alias' -- "$@"
}
Ta funkcja powłoki cytuje każdą tablicę arg, którą jej podajesz, i zwiększa jej wynik na iterowalny argument.
Oto kilka argumentów:
aq \
"here's an
ugly one" \
"this one is \$PATHpretty bad, too" \
'this one```****```; totally sucks'
WYNIK
1='here'"'"'s an
ugly one'
2='this one is $PATHpretty bad, too'
3='this one```****```; totally sucks'
To wyjście, z dashktórego typowo bezpieczne cytaty zawierają pojedyncze cytaty '"'"'.bashzrobiłby '\''.
Zastąpienie wyboru pojedynczych bajtów niepustych białych znakami o wartości innej niż null innym pojedynczym bajtem można prawdopodobnie zrobić najszybciej w dowolnej powłoce POSIX za pomocą $IFSi $*.
set -f; IFS=\"\'\`; set -- $var; printf %s "$*"
WYNIK
"some ""crazy """"""""string ""here
Tam właśnie printfto widzę, ale oczywiście, gdybym to zrobił:
var="$*"
... zamiast printfpolecenia$var „s wartość byłaby co widać w tam wyjście.
Kiedy set -finstruuję powłokę, aby nie globowała - w przypadku gdy łańcuch zawiera znaki, które można by interpretować jako wzorce globu. Robię to, ponieważ parser powłok rozszerza wzorce globu po dokonaniu podziału pól na zmienne. globbing może być ponownie włączony jak set +f. Ogólnie rzecz biorąc - w skryptach - przydatne jest ustawienie huku w następujący sposób:
#!/usr/bin/sh -f
A następnie, aby jawnie włączyć globowanie z set +fdowolną linią, której bym tego chciał.
Podział pola następuje na podstawie znaków w $IFS.
Istnieją dwa rodzaje $IFSwartości - $IFSbiałe znaki i $IFSinne znaki. $IFSspacje (spacja, tabulator, nowa linia) pola rozdzielane są określane tak, aby następowały po nich sekwencje do pojedynczego pola (lub wcale, jeśli nie poprzedzają czegoś innego) - więc ...
IFS=\ ; var=' '; printf '<%s>' $var
<>
Ale wszystkie inne są określone, aby oceniać do jednego pola na wystąpienie - nie są obcinane.
IFS=/; var='/////'; printf '<%s>' $var
<><><><><>
Wszystkie rozszerzenia zmiennych są domyślnie $IFSograniczonymi tablicami danych - są one podzielone na osobne pola zgodnie z $IFS. Kiedy ty" cytujesz jedną, zastępujesz tę właściwość tablicy i oceniasz ją jako pojedynczy ciąg.
Więc kiedy to zrobię ...
IFS=\"\'\`; set -- $var
Ustawiam tablicę argumentów powłoki na wiele $IFSrozdzielanych pól generowanych przez $varrozszerzenie. Po rozwinięciu jego wartości składowe dla zawartych w nim znaków $IFSsą tracone - są one teraz tylko separatorami pól - są\0NUL .
"$*"- podobnie jak inne podwójnie cytowane rozwinięcia zmiennych - również zastępuje właściwości podziału pola na $IFS. Ale dodatkowo zastępuje pierwszy bajt w $IFS każdym rozdzielanym polu w "$@". Tak, ponieważ "był pierwszy wartość $IFS wszystkich kolejnych ograniczniki stać "w "$*". I "nie trzeba też być $IFSprzy podziale. Można zmieniać $IFS po set -- $args innej wartości w całości i jego nowy pierwszy bajt by następnie pokazać się na ograniczniki polowych w "$*". Co więcej, możesz całkowicie usunąć wszystkie ich ślady:
set -- $var; IFS=; printf %s "$*"
WYNIK
some crazy string here
tr. PEH BASH jest dobry, ale w tym przypadku tr jest znacznie szybszy. np.echo "$OUTPUT" | tr -dc '[[:alpha:]]'ponieważ chcesz mieć tylko alfanumeryczne