Łączenie argumentów bash w pojedynczy ciąg ze spacjami

39

Próbuję połączyć wszystkie argumenty z funkcją Bash w jeden ciąg znaków ze spacjami oddzielającymi każdy argument. Potrzebuję również, aby ciąg zawierał pojedyncze cudzysłowy wokół całego łańcucha.

Oto co mam do tej pory ...

$array=("$@")
str="\'"
for arg in "${array[@]}"; do
    let $str=$str+$arg+" "
done
let $str=$str+"\'"

Oczywiście to nie działa, ale zastanawiam się, czy istnieje sposób, aby to osiągnąć?

Schwagmister
źródło

Odpowiedzi:

54

Wierzę, że robi to, co chcesz. Umieści wszystkie argumenty w jednym ciągu, oddzielone spacjami, z pojedynczymi cudzysłowami wokół wszystkich:

str="'$*'"

$*tworzy wszystkie argumenty skryptów oddzielone pierwszym znakiem $IFS, którego domyślnie jest spacja.

Wewnątrz ciągu podwójnego cudzysłowu nie ma potrzeby unikania pojedynczych cudzysłowów.

Przykład

Umieśćmy powyższe w pliku skryptu:

$ cat script.sh 
#!/bin/sh
str="'$*'"
echo "$str"

Teraz uruchom skrypt z przykładowymi argumentami:

$ sh script.sh one two three four 5
'one two three four 5'

Ten skrypt to POSIX. Będzie działać, bashale nie wymaga bash.

Odmiana: łączenie z ukośnikami zamiast spacji

Możemy zmienić spacje na inną postać, dostosowując IFS:

$ cat script.sh 
#!/bin/sh
old="$IFS"
IFS='/'
str="'$*'"
echo "$str"
IFS=$old

Na przykład:

$ sh script.sh one two three four       
'one/two/three/four'
John1024
źródło
Ok działało świetnie i zrobiłem dokładnie to, czego potrzebowałem. Próbuję tego użyć, aby zmienić katalog na katalog ze spacjami w nazwie tylko za pomocą argumentów. Ostatecznie potrzebowałem tego, aby stworzyć funkcję, która zmieni katalogi bez konieczności wpisywania apostrofów, jeśli katalog zawiera rozłożone słowa. Właśnie próbowałem: cdm () {str = "'$ *'" cd $ str}
Uzyskuje
@ Schwagmister: Możesz zapisać go w zmiennej (łańcuchowej), jeśli chcesz, ale jeśli nie musisz tego specjalnie robić, myślę, że cd "$*"będzie wystarczająco dobry.
Scott
@ Schwagmister Pojedyncze cytaty nie są tam pomocne. Spróbuj: cdm(){ str="$*"; cd "$str"; }albo, jak sugeruje Scott cdm(){ cd "$*"; }. Należy również pamiętać, że $*zastępuje wiele kolejnych spacji jedną spacją. Jeśli nazwa katalogu może zawierać wiele następujących po sobie spacji, tabulatorów lub znaków nowej linii, znaki te naprawdę muszą być poprzedzone znakiem ucieczki przed przekazaniem ich do cdmfunkcji.
John1024
Więc jeśli jest to coś w rodzaju testu 2 wersja próbna 1, to jak sprawiłbym, aby to polecenie cd działało poprawnie? To także niesamowita pomoc, naprawdę doceniam to chłopaki. @Scott
Schwagmister
@Schwagmister najlepiej jest umieścić apostrofy w wierszu poleceń podczas wywoływania cdmna przykład: cdm 'test 2 trial 1'. To obsłuży cały dwór o dziwnych nazwach. Jednak dopóki białe spacje są ograniczone do pojedynczych spacji, wówczas cdmmożna go uruchomić jako cdm test 2 trial 1.
John1024
5

To łatwiejsze niż myślisz:

#!/bin/bash
array="${@}"

echo $array

chmod + x that i uruchom go:

$ ./example.sh --foo bar -b az 
--foo bar -b az
Klaatu von Schlacker
źródło