function foo() {
[email protected]
echo $A
}
foo bla "hello ppl"
Chcę wyjście będzie:
„bla” „Hello ppl”Bash: Łączy wszystkie argumenty i owinąć je cudzysłowy
Co muszę zrobić zamiast elipsy?
function foo() {
[email protected]
echo $A
}
foo bla "hello ppl"
Chcę wyjście będzie:
„bla” „Hello ppl”Bash: Łączy wszystkie argumenty i owinąć je cudzysłowy
Co muszę zrobić zamiast elipsy?
Można użyć „$ @” traktować każdy parametr jako dobrze, oddzielny parametru, a następnie w pętli nad każdym parametrem:
function foo() {
for i in "[email protected]"
do
echo -n \"$i\"" "
done
echo
}
foo bla "hello ppl"
+1 To rozwiązanie działa! Jestem leniwy, więc zwykle upuszczam część "w" $ @ "i używam tylko" na " –
. Zapomniałem o tym wspomnieć w pytaniu, ale zamierzałem to zrobić bez użycia pętli. Szukałem jakiejś magicznej ekspansji bashów. – rui
ninjalj miał prawo pomysł, ale korzystanie z cytatów było dziwne częściowo dlatego, że to, o co prosi OP, nie jest najlepszym formatem wyjściowym dla wielu zadań powłoki. Właściwie nie mogę dowiedzieć się, co ma za zadanie, ale:
function quote_args {
for i ; do
echo \""$i"\"
done
}
stawia swoje argumenty za cytowany jedną linię, która jest zwykle najlepszym sposobem, aby karmić innych programów. Dostaniesz wyjście w formie, że nie poprosi o:
$ quote_args this is\ a "test really"
"this"
"is a"
"test really"
ale można ją łatwo przekształcić i to jest idiom, że większość wolałaby powłoki inwokacje:
$ echo `quote_args this is\ a "test really"`
"this" "is a" "test really"
ale chyba że jest przechodząc kolejną przepustkę eval
, dodatkowe cytaty prawdopodobnie zepsują rzeczy. Oznacza to, że ls "is a file"
pokaże plik is a file
podczas
$ ls `quote_args is\ a\ file`
spróbuje listy "is
, a
i file"
który prawdopodobnie nie ma.
Nie pętla wymagane:
foo() { local saveIFS=$IFS; local IFS='"'; local a="${*/#/ \"}"; echo "$a"\"; IFS=$saveIFS; }
Zapisywanie IFS
nie jest konieczne w tym prostym przykładzie, zwłaszcza przywrócenie go tuż przed zakończeniem czynności, ze względu na fakt, że local
jest używany. Jednak uwzględniłem to na wypadek, gdyby inne rzeczy wchodziły w funkcję, która może wpłynąć na zmienioną wersję.
Przykład uruchomić:
$ foo a bcd "efg hij" k "lll mmm nnn " ooo " ppp qqq " rrr\ sss
"a" "bcd" "efg hij" "k" "lll mmm nnn " "ooo" " ppp qqq " "rrr sss"
pomocą parametru podstawienie dodać "na początku i sufiks:
function foo() {
A=("${@/#/\"}")
A=("${A[@]/%/\"}")
echo -e "${A[@]}"
}
foo bla "hello ppl" kkk 'ss ss'
wyjściowy
"bla" "hello ppl" "kkk" "ss ss"
@msw ma rację (w górę komentarze na pytanie).Jednak inny pomysł, aby wydrukować argumenty z cytatami: używać niejawny iteracji printf
:
foo() { printf '"%s" ' "[email protected]"; echo ""; }
foo bla "hello ppl"
# => "bla" "hello ppl"
Ding! Wygrywasz dużą nagrodę. Gigantyczny pluszowy miś lub cztero-stopowy bank na monety? –
Dlaczego dodałeś echo ""; na końcu? Czy to nie jest konieczne. – EminezArtus
Tak więc wyjście zakończyłoby się znakiem nowej linii. Po prostu wygląda ładnie i nie zepsuje podpowiedzi. Rozumiem, że jest to niepotrzebne, gdy zostanie wywołane z poleceniem podstawienia –
Jedynym rozwiązaniem w tym momencie, że szanuje backslashy i cytaty wewnątrz argumentu:
$ concatenate() { printf "%q"" " "[email protected]"; echo ""; }
$ concatenate arg1 "arg2" "weird arg3\\\\\\bbut\" legal!"
arg1 arg2 weird\ arg3\\\\\\bbut\"\ legal\!
Zawiadomienie " % q "" "
% q argument jest drukowany w formacie, który może być ponownie wykorzystany jako ona ll wprowadzanie, unikanie znaków niedrukowalnych za pomocą proponowanej składni POSIX $ 1 'za pomocą .
znaki specjalne (\
, \b
Backspace ...) rzeczywiście będzie interpretowany przez program odbiorczym, nawet jeśli nie są wyświetlane interpretowane wyjścia terminala. Test
Miejmy:
# display.sh: Basic script to display the first 3 arguments passed
echo -e '#!/bin/bash'"\n"'echo -e "\$1=""$1"; echo -e "\$2=""$2"; echo -e "\$3=""$3"; sleep 2;' > display.sh
sudo chmod 755 display.sh
# Function to concatenate arguments as $ARGS
# and "evalutate" the command display.sh $ARGS
test_bash() { ARGS=$(concatenate "[email protected]"); bash -c "./display.sh ""$ARGS"; }
# Test: Output is identical whatever the special characters
./display.sh arg1 arg2 arg3
test_bash arg1 arg2 arg3
Więcej testy komplikować:
./display.sh arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"
test_bash arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"
W display.sh
używamy echo -e
zamiast tylko echo
lub printf
w celu interpretowania znaków specjalnych. Jest to tylko reprezentatywne, jeśli Twój program je interpretuje.
-e umożliwiają interpretację backslashem uchodzi
Jeśli -e obowiązuje następujące sekwencje rozpoznawane:
- \ ukośnikowe
- \ alert (B)
- \ b backspace
- Itp.
NB: \b
jest znakiem backspace, więc kasuje Y w przykładzie.
Zauważ, że ten przykład nie ma być powielana w prawdziwym kodzie:
bash -c
i screen -X
Przyjmuj kilka argumentów, więc nie ma potrzeby używania konkatenacji: zobacz Can't seem to use bash -c option with arguments after the -c option string). Po prostu pamiętaj o przekazaniu czegoś dla $0
podczas korzystania z bash -c
.Dzięki przyjętej odpowiedzi i Danny Hong answer w "Jak uniknąć podwójnego cudzysłowu wewnątrz podwójnego cudzysłowu?"
Co próbujesz osiągnąć?Czy dane wyjściowe 'foo' mogą być użyte jako dane wejściowe do niczego lub czy chcesz tylko tekst nieprzetworzony? – msw
To powinno być użyte jako dane wejściowe dla innego polecenia (w tym przypadku poczta). – rui
@rubim: wtedy myślę, że robisz to znacznie trudniej, niż to konieczne. 'mail" $ @ "' dałoby wyniki bez kroku parsowania/ponownej analizy. Jeśli '" $ @ "' nie jest we właściwym stanie, pokaż, co masz. – msw