J'ai un script shell avec ce code:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
Mais le code conditionnel s'exécute toujours, car hg st
imprime toujours au moins un caractère de nouvelle ligne.
- Existe-t-il un moyen simple de supprimer les espaces
$var
(commetrim()
en PHP )?
ou
- Existe-t-il un moyen standard de traiter ce problème?
Je pourrais utiliser sed ou AWK , mais j'aimerais penser qu'il existe une solution plus élégante à ce problème.
$ var=$(echo)
$ [ -n $var ]; echo $? #undesired test return
0
$ [[ -n $var ]]; echo $?
1
echo " This is a string of char " | xargs
. Si vous avez cependant une seule citation dans le texte que vous pouvez faire ce qui suit:echo " This i's a string of char " | xargs -0
. Notez que je mentionne le dernier des xargs (4.6.0)test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi
, mais cela le feratest=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi
- il doit donc y avoir plus qu'une simple nouvelle ligne à la fin.echo $A | sed -r 's/( )+//g'
;Réponses:
Définissons une variable contenant des espaces de début, de fin et intermédiaires:
Comment supprimer tous les espaces (indiqués par
[:space:]
intr
):Comment supprimer uniquement les espaces principaux:
Comment supprimer uniquement les espaces de fin:
Comment supprimer les espaces de début et de fin - enchaînez les
sed
s:Alternativement, si votre bash le prend en charge, vous pouvez le remplacer
echo -e "${FOO}" | sed ...
parsed ... <<<${FOO}
, comme ceci (pour les espaces de fin):la source
tr
etsed
par[[:space:]]
. Notez que l'sed
approche ne fonctionnera que sur une entrée sur une seule ligne . Pour les approches qui fonctionnent avec une entrée multiligne et utilisent également les fonctionnalités intégrées de bash, consultez les réponses de @bashfu et @GuruM. Une version en ligne généralisée de la solution de @Nicholas Sushkin ressemblerait à ceci:trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"
à votre~/.profile
permet d'utiliserecho $SOMEVAR | trim
etcat somefile | trim
.sed
solution qui utilise une seule expression au lieu de deux:sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/'
. Il coupe les espaces blancs de début et de fin et capture toutes les séquences séparées par des espaces de caractères non blancs au milieu. Prendre plaisir!|
, afin de la garder comme une seule expression, plutôt que plusieurs.Une réponse simple est:
Xargs fera le réglage pour vous. C'est une commande / programme, pas de paramètres, renvoie la chaîne coupée, aussi simple que ça!
Remarque: cela ne supprime pas tous les espaces internes et
"foo bar"
reste donc le même; cela ne devient PAS"foobar"
. Cependant, plusieurs espaces seront condensés en espaces uniques, ainsi"foo bar"
le deviendra"foo bar"
. De plus, il ne supprime pas les caractères de fin de ligne.la source
xargs echo
juste pour être bavard sur ce que je fais, mais xargs à lui seul utilisera echo par défaut.sed 's/ *$//'
comme alternative. Vous pouvez voir laxargs
nouvelle ligne comme ceci:echo -n "hey thiss " | xargs | hexdump
vous remarquerez0a73
quea
c'est la nouvelle ligne. Si vous faites de même avecsed
:echo -n "hey thiss " | sed 's/ *$//' | hexdump
vous verrez0073
, pas de nouvelle ligne.a<space><space>b
ena<space>b
. 2. Plus encore: il se transformeraa"b"c'd'e
enabcde
. 3. Encore plus: il échoueraa"b
, etc.Il existe une solution qui n'utilise que des Bash intégrés appelés caractères génériques :
Voici le même enveloppé dans une fonction:
Vous passez la chaîne à couper sous forme de guillemets. par exemple:
Une bonne chose à propos de cette solution est qu'elle fonctionnera avec n'importe quel shell compatible POSIX.
Référence
la source
s=" 1 2 3 "; echo \""${s%1 2 3 }"\"
couperait tout de la fin, renvoyant le leader" "
. Subbing1 2 3
avec lui[![:space:]]*
dit de "trouver le premier caractère non-espace, puis de le tapoter et tout ce qui suit". L'utilisation%%
au lieu de%
rend l'opération de découpage de fin gourmande. Ceci est imbriqué dans un découpage non gourmand dès le début, donc en fait, vous découpez" "
depuis le début. Ensuite, échangez%, # et * pour les espaces de fin. Bam!/bin/sh
(uniquement avec/usr/xpg4/bin/sh
, mais ce n'est pas ce qui sera utilisé avec les scripts sh habituels).${var%%[![:space:]]*}
dit "supprimer devar
sa plus longue sous-chaîne qui commence par un caractère non-espace". Cela signifie que vous ne disposez que des espaces de tête, que vous supprimez par la suite${var#..
. La ligne suivante (arrière) est l'inverse.awk
,sed
,tr
,xargs
) simplement d'une suppression des espaces chaîne unique est fondamentalement fou - en particulier lorsque la plupart des shells (y compris bash) déjà fournir la chaîne native munging installations hors-the-box.Bash a une fonctionnalité appelée expansion de paramètres , qui, entre autres, permet le remplacement de chaînes basé sur des soi-disant modèles (les modèles ressemblent à des expressions régulières, mais il existe des différences et des limitations fondamentales). [ligne originale de flussence: Bash a des expressions régulières, mais elles sont bien cachées:]
Ce qui suit montre comment supprimer tout l'espace blanc (même de l'intérieur) d'une valeur variable.
la source
${var/ /}
supprime le premier caractère d'espace.${var// /}
supprime tous les caractères d'espace. Il n'y a aucun moyen de couper simplement les espaces de début et de fin avec uniquement cette construction.Afin de supprimer tous les espaces du début et de la fin d'une chaîne (y compris les caractères de fin de ligne):
Cela supprimera également les espaces en double:
Produit: 'cette chaîne a beaucoup d'espaces'
la source
echo -n
?echo " my string " | xargs
a la même sortie.Supprimer un espace de tête et un espace de fin
Par exemple:
Production:
Supprimez tous les espaces avant et arrière
Par exemple:
Production:
la source
'hello world ', 'foo bar', 'both sides '
De la section Bash Guide sur le globbing
Pour utiliser un extglob dans une extension de paramètre
Voici la même fonctionnalité enveloppée dans une fonction (REMARQUE: besoin de citer la chaîne d'entrée passée à la fonction):
Usage:
Si nous modifions la fonction à exécuter dans un sous-shell, nous n'avons pas à nous soucier d'examiner l'option de shell actuelle pour extglob, nous pouvons simplement la définir sans affecter le shell actuel. Cela simplifie énormément la fonction. Je mets aussi à jour les paramètres de position "en place" donc je n'ai même pas besoin d'une variable locale
donc:
la source
extglob
, en utilisantshopt -p
: écrivez simplementlocal restore="$(shopt -p extglob)" ; shopt -s extglob
au début de votre fonction, eteval "$restore"
à la fin (sauf, accordé, eval est mauvais…).[[:space:]]
pourrait être remplacé par, eh bien, un espace:${var##+( )}
et${var%%+( )}
fonctionner aussi bien et ils sont plus faciles à lire.Vous pouvez couper simplement avec
echo
:la source
foo
contient un caractère générique? par exemple,foo=" I * have a wild card"
... surprise! De plus, cela réduit plusieurs espaces contigus en un seul.Je l'ai toujours fait avec sed
S'il existe une solution plus élégante, j'espère que quelqu'un l'affichera.
la source
sed
?sed -e 's/\s*$//'
. Explication: «s» signifie recherche, «\ s» signifie tous les espaces, «*» signifie zéro ou plusieurs, «$» signifie jusqu'à la fin de la ligne et «//» signifie remplacer toutes les correspondances par une chaîne vide .Vous pouvez supprimer les sauts de ligne avec
tr
:la source
Avec les fonctionnalités étendues de correspondance de motifs de Bash activées (
shopt -s extglob
), vous pouvez utiliser ceci:{trimmed##*( )}
pour supprimer une quantité arbitraire d'espaces de tête.
la source
/bin/sh -o posix
fonctionne aussi mais je suis méfiant.trimmed
? Est-ce une chose intégrée ou la variable qui est coupée?la source
read
stockera à la variable par son nom $ 1 une version tronquée de sa valeur $ {! 1}trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
read -rd '' str <<<"$str"
fera l'affaire.Il y a beaucoup de réponses, mais je crois toujours que mon script qui vient d'être écrit mérite d'être mentionné parce que:
"$*"
joint plusieurs arguments en utilisant un seul espace. si vous voulez couper et sortir uniquement le premier argument, utilisez"$1"
plutôtLe scénario:
Usage:
Production:
la source
[\ \t]
[[:space:]]
comme dans l'une des autres réponses: stackoverflow.com/a/3352015/3968618Vous pouvez utiliser la vieille école
tr
. Par exemple, cela renvoie le nombre de fichiers modifiés dans un référentiel git, espaces blancs supprimés.la source
Cela a fonctionné pour moi:
Pour mettre cela sur moins de lignes pour le même résultat:
la source
${var##Pattern}
pour plus de détails. En outre, ce site explique les modèles de bash . Ainsi, les##
moyens suppriment le motif donné de l'avant et les%%
moyens suppriment le motif donné de l'arrière. La+( )
partie est le motif et cela signifie "une ou plusieurs occurrences d'un espace"OU
OU
OU
OU
S'appuyer sur l'expr soulution de moskit ...
OU
la source
J'ai vu des scripts utiliser simplement l'affectation de variables pour faire le travail:
Les espaces sont automatiquement fusionnés et rognés. Il faut faire attention aux métacaractères du shell (risque d'injection potentiel).
Je recommanderais également toujours de remplacer les variables par des guillemets doubles dans les conditions de la coque:
car quelque chose comme un -o ou un autre contenu dans la variable pourrait modifier vos arguments de test.
la source
$xyz
avececho
qui fait la fusion des espaces blancs, pas l'affectation des variables. Pour stocker la valeur ajustée dans la variable de votre exemple, vous devez utiliserxyz=$(echo -n $xyz)
. De plus, cette approche est sujette à une expansion potentiellement indésirable des chemins (globbing).xyz
variable n'est PAS coupée.la source
echo $(echo "1 2 3")
(avec deux espaces entre 1, 2 et 3).J'utiliserais simplement sed:
a) Exemple d'utilisation sur une chaîne à ligne unique
Production:
b) Exemple d'utilisation sur une chaîne multiligne
Production:
c) Remarque finale:
Si vous n'aimez pas utiliser une fonction, pour une chaîne à une seule ligne, vous pouvez simplement utiliser une commande "plus facile à retenir" comme:
Exemple:
Production:
L'utilisation de ce qui précède sur les chaînes multi-lignes fonctionnera également , mais veuillez noter que cela réduira également tout espace multiple interne à la fin / en tête, comme GuruM l'a remarqué dans les commentaires.
Production:
Donc, si cela vous dérange de garder ces espaces, veuillez utiliser la fonction au début de ma réponse!
d) EXPLICATION de la syntaxe sed "find and replace" sur les chaînes multilignes utilisées à l'intérieur de la fonction trim:
la source
Voici une fonction trim () qui coupe et normalise les espaces blancs
Et une autre variante qui utilise des expressions régulières.
la source
*
caractère dans la chaîne d'entrée soit étendre à tous les fichiers et dossiers du dossier de travail actuel. Enfin, si $ IFS est défini sur une valeur non définie par défaut, le découpage peut ne pas fonctionner (bien que cela soit facilement résolu par l'ajoutlocal IFS=$' \t\n'
). Le découpage est limité aux formes d'espaces suivants: les espaces\t
et les\n
caractères.if
ligne avec:if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]
. Enfin, l'approche ne concerne que les espaces, pas les autres formes d'espaces (voir mon prochain commentaire).if
ligne par:[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
Utilisez AWK:
la source
$stripped_version=
echo $ var | awk '{gsub (/ ^ + | + $ /, "")} 1' 'Les affectations ignorent les espaces blancs de début et de fin et, en tant que telles, peuvent être utilisées pour couper:
la source
echo "$var"
pour voir la valeur avec des espaces.var=$(echo $var)
mais je ne le recommande pas. Les autres solutions présentées ici sont préférées.Cela ne pose pas de problème avec les globes indésirables, également, l'espace blanc intérieur n'est pas modifié (en supposant que
$IFS
est défini par défaut, ce qui est' \t\n'
).Il lit jusqu'à la première nouvelle ligne (et ne l'inclut pas) ou la fin de la chaîne, selon la première éventualité, et supprime tout mélange d'espaces et de
\t
caractères de début et de fin . Si vous souhaitez conserver plusieurs lignes (et également supprimer les sauts de ligne de début et de fin), utilisezread -r -d '' var << eof
plutôt; notez cependant que si votre entrée contient\neof
, elle sera coupée juste avant. ( D' autres formes d'espace blanc, à savoir\r
,\f
et\v
, sont ne pas supprimées, même si vous les ajoutez à $ IFS.)la source
Pour supprimer les espaces et les tabulations de gauche à premier mot, entrez:
cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html
la source
Cela supprimera tous les espaces blancs de votre chaîne,
/
remplace la première occurrence et//
toutes les occurrences d'espaces dans la chaîne. C'est-à-dire que tous les espaces blancs sont remplacés par - rienla source
C'est la méthode la plus simple que j'ai vue. Il utilise uniquement Bash, ce ne sont que quelques lignes, l'expression rationnelle est simple et correspond à toutes les formes d'espaces:
Voici un exemple de script pour le tester:
la source
^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
Python a une fonction
strip()
qui fonctionne de manière identique à PHPtrim()
, donc nous pouvons simplement faire un peu de Python en ligne pour en faire un utilitaire facilement compréhensible:Cela supprimera les espaces de début et de fin (y compris les retours à la ligne).
la source
la source
J'ai trouvé que j'avais besoin d'ajouter du code à partir d'une
sdiff
sortie en désordre pour le nettoyer:Cela supprime les espaces de fin et autres caractères invisibles.
la source
Suppression d'espaces dans un espace:
la source