Unindo argumentos bash em uma única string com espaços

40

Estou tentando associar todos os argumentos a uma função Bash em uma única seqüência de caracteres com espaços que separam cada argumento. Também preciso que a string inclua aspas simples em toda a string.

Aqui está o que eu tenho até agora ...

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

Obviamente, isso não funciona, mas eu estou querendo saber se existe uma maneira de conseguir isso?

Schwagmister
fonte

Respostas:

57

Eu acredito que isso faz o que você quer. Colocará todos os argumentos em uma sequência, separados por espaços, com aspas simples em torno de todos:

str="'$*'"

$*produz todos os argumentos de scripts separados pelo primeiro caractere dos $IFSquais, por padrão, é um espaço.

Dentro de uma sequência de aspas duplas, não há necessidade de escapar aspas simples.

Exemplo

Vamos colocar o acima em um arquivo de script:

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

Agora, execute o script com argumentos de amostra:

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

Este script é POSIX. Ele funcionará, bashmas não requer bash.

Uma variação: concatenar com barras em vez de espaços

Podemos mudar de espaços para outro caractere ajustando IFS:

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

Por exemplo:

$ sh script.sh one two three four       
'one/two/three/four'
John1024
fonte
Ok, isso funcionou muito bem e fez exatamente o que eu precisava. Estou tentando usar isso para alterar o diretório para um diretório com espaços no nome apenas usando os argumentos. O que eu finalmente precisava disso era criar uma função que alterasse os diretórios sem precisar digitar os apóstrofos se o diretório tivesse palavras espaçadas. O que eu acabei de tentar foi o seguinte: cdm () {str = "'$ *'" cd $ str} Ele acessa apenas o primeiro argumento em str Por exemplo: cdm test 2 Resultado: 'test:' test: nenhum arquivo ou diretório
Schwagmister
@ Schwagmister: Você pode salvá-lo em uma variável (string) se quiser, mas, se você não precisar especificamente fazer isso, acho cd "$*"que será bom o suficiente.
Scott
@ Schwagmister As aspas simples não são úteis lá. Tente: cdm(){ str="$*"; cd "$str"; }ou, como Scott sugere cdm(){ cd "$*"; },. Além disso, esteja ciente de que $*substitui vários espaços consecutivos por um único espaço. Se o nome do diretório pode ter vários espaços consecutivos, tabulações ou novas linhas, esses caracteres realmente precisam ser escapados antes de serem passados ​​para a cdmfunção.
precisa saber é o seguinte
Portanto, se for algo como o teste 2, avaliação 1, como eu faria esse comando cd funcionar corretamente? Também é uma ajuda incrível, eu realmente aprecio isso, pessoal. @Scott
Schwagmister
@Schwagmister A melhor maneira é colocar aspas simples na linha de comando ao chamar cdmcomo em: cdm 'test 2 trial 1'. Isto irá lidar com toda a mansão de nomes estranhos. No entanto, desde que os espaços em branco sejam limitados a espaços únicos, cdmele poderá ser executado como cdm test 2 trial 1.
John1024
5

É mais fácil do que você pensa:

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

echo $array

chmod + x isso e execute-o:

$ ./example.sh --foo bar -b az 
--foo bar -b az
Klaatu von Schlacker
fonte