web-dev-qa-db-fra.com

Joindre des arguments bash en une seule chaîne avec des espaces

J'essaie de joindre tous les arguments d'une fonction Bash en une seule chaîne avec des espaces séparant chaque argument. J'ai également besoin que la chaîne inclue des guillemets simples autour de la chaîne entière.

Voici ce que j'ai jusqu'à présent ...

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

Évidemment, cela ne fonctionne pas, mais je me demande s'il existe un moyen d'y parvenir?

46
Schwagmister

Je crois que cela fait ce que vous voulez. Il mettra tous les arguments dans une chaîne, séparés par des espaces, avec des guillemets simples autour de tous:

str="'$*'"

$* produit tous les arguments des scripts séparés par le premier caractère de $IFS qui, par défaut, est un espace.

À l'intérieur d'une chaîne entre guillemets doubles, il n'est pas nécessaire d'échapper les guillemets simples.

Exemple

Mettons ce qui précède dans un fichier script:

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

Maintenant, exécutez le script avec des exemples d'arguments:

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

Ce script est POSIX. Cela fonctionnera avec bash mais il ne nécessite pas bash.

Une variante: concaténation avec des barres obliques au lieu d'espaces

Nous pouvons passer d'espaces à un autre caractère en ajustant IFS:

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

Par exemple:

$ sh script.sh one two three four       
'one/two/three/four'
69
John1024

C'est plus facile que vous ne le pensez:

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

echo $array

chmod + x ça, et lancez-le:

$ ./example.sh --foo bar -b az 
--foo bar -b az
5

mise à jour Tl; dr, utilisez

"'${array[*]}'"

Pour être clair, je n'ai pas l'intention de reproduire cette réponse . Je viens de découvrir qu'il existe des différences mineures à utiliser @ et * pour déréférencer toutes les valeurs d'un tableau.

Sous la capuche, $* et $@ sont tous des tableaux, faisant référence à la liste argv.

De la question,

J'essaye de joindre tous les arguments à une fonction Bash en une seule chaîne avec des espaces séparant chaque argument.

Il comporte 2 sous-questions:

  1. concaténer les arguments d'entrée du tableau dans une chaîne.
  2. passez la chaîne concaténée comme un seul argument pour la fonction Shell.

Tout d'abord, concattez le tableau dans une chaîne,

array=("$@")
str="'${array[@]}'"
# or
str="'${array[*]}'"
# or
str=\'"${array[*]}"\'

Deuxièmement, lorsque vous passez str à une fonction, comptons le nombre d'arguments reçus par cette fonction,

#!/usr/bin/env bash

arr=(a b c d)

function count_args() {
  echo '$#' $#
}

count_args "'${arr[@]}'"
count_args \'"${arr[@]}"\'
count_args "'${arr[*]}'"
count_args \'"${arr[*]}"\'

la sortie est

$# 4
$# 4
$# 1
$# 1

seulement arr[*] enveloppe le tableau en 1 argument pour la fonction Shell, pourquoi?

Cite de Comment utiliser les tableaux dans le script bash , que j'ai trouvé utile pour moi,

echo ${array[*]}
echo ${array[@]}

Les deux syntaxes nous permettent d'accéder à toutes les valeurs du tableau et de produire les mêmes résultats, à moins que l'expansion ne soit citée . Dans ce cas, une différence survient: dans le premier cas, lors de l'utilisation de @, l'expansion se traduira par un mot pour chaque élément du tableau.

Alors que l'utilisation de * regroupera l'ensemble du tableau en un seul argument lors de l'expansion.

0
Izana