J'ai une chaîne contenant de nombreux mots avec au moins un espace entre les deux. Comment puis-je diviser la chaîne en mots individuels afin de pouvoir les parcourir?
La chaîne est passée en argument. Par exemple ${2} == "cat cat file"
. Comment puis-je le parcourir?
De plus, comment puis-je vérifier si une chaîne contient des espaces?
Réponses:
Avez-vous essayé de simplement passer la variable chaîne à une
for
boucle? Bash, pour sa part, se divisera automatiquement sur les espaces.la source
A=${A}${word})
.touch NOPE; var='* a *'; for a in $var; do echo "[$a]"; done
sorties[NOPE] [a] [NOPE]
au lieu des attentes[*] [a] [*]
(LF remplacés par SPC pour plus de lisibilité).J'aime la conversion en tableau, pour pouvoir accéder aux éléments individuels:
vous pouvez maintenant accéder directement aux éléments individuels (il commence par 0):
ou reconvertissez en chaîne pour boucler:
Bien sûr, le fait de boucler directement dans la chaîne a été répondu auparavant, mais cette réponse avait l'inconvénient de ne pas suivre les éléments individuels pour une utilisation ultérieure:
Voir aussi Bash Array Reference .
la source
touch NOPE; var='* a *'; arr=($var); set | grep ^arr=
sortiesarr=([0]="NOPE" [1]="a" [2]="NOPE")
au lieu des attentesarr=([0]="*" [1]="a" [2]="*")
Utilisez simplement les coques "set" intégrées. Par exemple,
Après cela, les mots individuels dans $ text seront dans $ 1, $ 2, $ 3, etc. Pour la robustesse, on fait généralement
pour gérer le cas où $ text est vide ou commencez par un tiret. Par exemple:
Ceci imprime
la source
awk
maisset
c'est beaucoup plus facile. Je suis maintenantset
fanboy. Merci @Idelic!touch NOPE; var='* a *'; set -- $var; for a; do echo "[$a]"; done
sorties[NOPE] [a] [NOPE]
au lieu de ce qui est attendu[*] [a] [*]
. Utilisez-le uniquement si vous êtes sûr à 101% qu'il n'y a pas de métacaractères SHELL dans la chaîne fractionnée!set -f
avantset -- $var
etset +f
après désactiver la globalisation.set -f
votre solution est sûr, aussi. Maisset +f
c'est la valeur par défaut de chaque shell, c'est donc un détail essentiel, qui doit être noté, car d'autres ne le savent probablement pas (comme moi aussi).Le moyen probablement le plus simple et le plus sûr dans BASH 3 et supérieur est:
(où
arr
est le tableau qui prend les parties fractionnées de la chaîne) ou, s'il peut y avoir des sauts de ligne dans l'entrée et que vous voulez plus que la première ligne:(veuillez noter l'espace dans
-d ''
, il ne peut pas être laissé de côté), mais cela pourrait vous donner une nouvelle ligne inattendue de<<<"$var"
(car cela ajoute implicitement un LF à la fin).Exemple:
Produit les résultats attendus
car cette solution (contrairement à toutes les solutions précédentes ici) n'est pas sujette à un globbing shell inattendu et souvent incontrôlable.
Cela vous donne également la pleine puissance d'IFS comme vous le souhaitez probablement:
Exemple:
Produit quelque chose comme:
Comme vous pouvez le voir, les espaces peuvent également être préservés de cette façon:
les sorties
Veuillez noter que la gestion de
IFS
BASH est un sujet en soi, alors faites vos tests, quelques sujets intéressants à ce sujet:unset IFS
: Ignore les exécutions de SPC, TAB, NL et commence et se termine en ligneIFS=''
: Pas de séparation de champ, lit toutIFS=' '
: Exécutions de SPC (et SPC uniquement)Un dernier exemple
les sorties
tandis que
les sorties
BTW:
Si vous n'avez pas l'habitude de
$'ANSI-ESCAPED-STRING'
vous y habituer, c'est un gain de temps.Si vous n'incluez pas
-r
(comme dansread -a arr <<<"$var"
), alors read n'échappe pas à la barre oblique inverse. Ceci est laissé comme exercice pour le lecteur.Pour la deuxième question:
Pour tester quelque chose dans une chaîne, je m'en tiens habituellement
case
, car cela peut vérifier plusieurs cas à la fois (remarque: la casse n'exécute que la première correspondance, si vous avez besoin d'utiliser descase
instructions de multiplication ), et ce besoin est assez souvent le cas (pun prévu):Vous pouvez donc définir la valeur de retour pour vérifier le SPC comme ceci:
Pourquoi
case
? Parce qu'il est généralement un peu plus lisible que les séquences d'expression régulière, et grâce aux métacaractères Shell, il gère très bien 99% de tous les besoins.la source
set -f
ouset -o noglob
changer de globbing, de sorte que les métacaractères du shell ne fassent plus de mal dans ce contexte. Mais je ne suis pas vraiment un ami de cela, car cela laisse beaucoup de puissance de la coque / est très enclin à commuter dans les deux sens ce paramètre.;&
parvenir. Je ne sais pas trop dans quelle version de bash est apparue. Je suis un utilisateur 4.3;&
est la chute forcée sans vérification de modèle comme en C. Et il y a aussi;;&
qui continue juste à faire les vérifications de modèle supplémentaires. Il en;;
est de mêmeif ..; then ..; else if ..
et;;&
est commeif ..; then ..; fi; if ..
, où;&
est commem=false; if ..; then ..; m=:; fi; if $m || ..; then ..
- on n'arrête jamais d'apprendre (des autres););;&
avant que vous commentiez: D Merci, et que le coquillage soit avec vous;)Pour vérifier les espaces, utilisez grep:
la source
echo "X" |
peut généralement être remplacé par<<<"X"
, comme ceci:grep -s " " <<<"This contains SPC"
. Vous pouvez voir la différence si vous faites quelque chose commeecho X | read var
contrairement àread var <<< X
. Seul ce dernier importe la variablevar
dans le shell courant, alors pour y accéder dans la première variante il faut grouper comme ceci:echo X | { read var; handle "$var"; }
(A) Pour diviser une phrase en ses mots (séparés par des espaces), vous pouvez simplement utiliser l'IFS par défaut en utilisant
Exemple d' exécution de l'extrait de code suivant
affichera
Comme vous pouvez le voir, vous pouvez également utiliser des guillemets simples ou doubles sans aucun problème
Remarques:
- c'est fondamentalement la même chose que la réponse de mob , mais de cette façon, vous stockez le tableau pour tout autre besoin. Si vous n'avez besoin que d'une seule boucle, vous pouvez utiliser sa réponse, qui est d'une ligne plus courte :)
- veuillez vous référer à cette question pour d'autres méthodes pour diviser une chaîne en fonction du délimiteur.
(B) Pour rechercher un caractère dans une chaîne, vous pouvez également utiliser une correspondance d'expression régulière.
Exemple pour vérifier la présence d'un caractère espace que vous pouvez utiliser:
la source
Pour vérifier les espaces uniquement avec bash:
la source
Cela génère chaque mot, vous pouvez traiter cette liste comme bon vous semble par la suite.
la source