Compte tenu de l'extrait de script du shell Bash suivant:
/usr/local/bin /usr/bin /bin
Ainsi, la ligne eval eval ...
dans le code précédent peut-elle être simplifiée, tout en produisant sortie souhaitée, qui pour l'exemple ci-dessus est:
# The intent is to take the PATH env variable, break it up into its parts, making them # appear to be command line args (i.e., `$1`, `$2`, ...), and then for this example, just # echo the parts in space delimited form, but we can imagine that we may want to do other # things with them - this is just sample usage # Important Requirement/Constraint # ================================ # Please do not alter the "PATH to $1, $2, $3, ..." portion of the answer or replace the # Bash ".." range construct with the output of the "seq" command exec'd in a subshell. # Preferably, the answer should simply consist of the simplification of the last line of # code - the "eval eval ..." . Also, please don't simplify by collapsing the whole thing # to just echo "$@" since we may want to work with only some of the parts, and not # necessarily the first parts, of the path. That is to say that the 1 and $# in the # {1..$#} range could be replaced with other shell variables or expr., potentially # Test case PATH=/usr/local/bin:/usr/bin:/bin # The code being examined follows # Set ':' as the input field separator of the path IFS=: # Or, more appropriately if in a function: local IFS=: # Parse the PATH environment variable and break it up into its components set $PATH # This is the line we want to simplify, if possible, without losing functionality of # course (see the comment that follows for details) eval eval echo '\'$(eval 'echo "\${1..$#}"') # Some notes and explanations regarding the functionality and underlying intent of the # preceding line: # - We start by dynamically creating the following construct: ${1..3} # since $# is 3 for our example # - Use Bash to expand that construct to: $1 $2 $3 # these vars contain the parsed parts of the PATH # - Finally, display the three parts of the PATH using echo: echo $1 $2 $3 # - This causes the following text to be sent to STDOUT: # /usr/local/bin /usr/bin /bin
Je pense à une solution qui remplacerait certaines des commandes echo
par redirection d'entrée / sortie (peut-être) ou peut-être une sorte de réorganisation / réduction qui entraînerait le besoin de moins de commandes eval
que celles utilisées dans l'exemple.
3 Réponses :
echo "${PATH}" | tr ':' '\n' > stack count=1 echo "#/bin/sh-" | tr '-' '\n' >> stack2 while read line do echo "path${count}=${line}" >> stack2 count=$(($count+1)) done < stack source stack2 Now you've got every section of the path, in its' own named variable.
Pas exactement ce que j'ai demandé, mais assez intéressant pour un vote positif.
L'approvisionnement narcissique est toujours apprécié.
En vous rapprochant de l'original, vous pouvez faire
set $(sed 's/[^=]*=//;s/:/ /g' <<< ${PATH}) echo "$@"
Si vous ne voulez pas changer IFS
et PATH
, vous peut faire
IFS=: set $PATH echo "$@"
Vous avez un point-virgule de trop, mon ami. Il doit être: set $ (sed 's / [^ =] * = //; s /: / / g' <<< $ {PATH}); echo "$ @"
. Certainement une prise intéressante, si ce n'est dans les lignes directrices de la question. Dans tous les cas, faites un vote positif ( et remplacez ce deuxième point-virgule dans la commande sed par un signe deux-points - ce n'est pas Windows ).
mais produit toujours le résultat souhaité,
/ usr / local / bin / usr / bin / binJuste :
IFS=':' read -ra patharr <<<"$PATH" set -- "${patharr[@]}" IFS=' '; printf "%s\n" "${patharr[*]}"L'intention est de prendre la variable d'environnement PATH, de la diviser en ses parties, en les faisant semblent être des arguments de ligne de commande (c'est-à-dire
$ 1
,$ 2
, ...), puis pour cet exemple, juste faire écho aux parties sous une forme délimitée par un espace, mais nous pouvons imaginer que nous voudrions peut-être faire d'autres choses avec eux - ceci est juste un exemple d'utilisationJe ne fais pas confiance aux extensions de shell sans guillemets.
echo "${PATH//:/ }"
J'irais pour le "effondrement de toutes sortes" comme l'indique @oguz ismail.
@oguz, j'ai expliqué que nous pourrions être intéressés par certains arguments et pas tous, c'était un exemple de plage équivalent à
"$ @"
. Voir la dernière phrase du commentaireExigence / Contrainte
intégré dans le codePourriez-vous déplacer la prose hors du bloc de code? Il est beaucoup plus facile à lire lorsqu'il est correctement formaté.
Ensuite, vous utiliseriez quelque chose comme
"$ {@: 1: 3}"
, pas eval.Je collerais les composants du chemin dans un tableau (pourquoi le définir sur des paramètres de position, nécessitant cette expansion sans guillemets?) Comme
IFS =: read -ra arr <<< "$ PATH"
et ensuite faire avec learr
tableau ce que je veux.@oguz, et lorsque vous paramétrez votre 1 et votre 3 pour qu'ils soient dynamiques, vous revenez à ma question initiale
Ensuite, vous utilisez une boucle
for ((...))
de style C.