J'ai une ficelle:
one_two_three_four_five
Je dois enregistrer dans une A
valeur de variable two
et dans la B
valeur four
de variable de la chaîne ci-dessus
Utilisez cut
avec _
comme délimiteur de champ et obtenez les champs désirés:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
Vous pouvez également utiliser echo
et pipe au lieu de la chaîne Here:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
Exemple:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
Savez-vous ce qui se passe ici?echo "${s##*_}"
En utilisant uniquement les constructions POSIX sh, vous pouvez utiliser des constructions de substitution de paramètres pour analyser un délimiteur à la fois. Notez que ce code suppose qu'il existe le nombre requis de champs, sinon le dernier champ est répété.
Vous pouvez également utiliser une substitution de paramètre non entre guillemets avec le développement de caractères génériques désactivé et
IFS
défini sur le caractère de délimitation (cela ne fonctionne que si le délimiteur est un seul caractère non blanc ou si une séquence d'espaces blancs est un délimiteur).Cela écrase les paramètres de position. Si vous faites cela dans une fonction, seuls les paramètres de position de la fonction sont affectés.
Une autre approche consiste à utiliser le mode
read
intégré.la source
unset IFS
ne retourne pasIFS
aux valeurs par défaut. Si après cela, quelqu'unOldIFS="$IFS"
aura une valeur nulle dans OldIFS. En outre, il est supposé que la valeur précédente de IFS est la valeur par défaut, ce qui est très possible (et utile) de ne pas l'être. La seule solution correcte est de stocker dansold="$IFS"
et de restaurer ultérieurement avec IFS = "$ old". Ou ... utilisez un sous-shell(...)
. Ou, mieux encore, lisez ma réponse.unset IFS
ne rétablitIFS
pas la valeur par défaut, mais renvoie la division du champ à l'effet par défaut. Oui, c'est une limitation, mais généralement acceptable dans la pratique. Le problème avec un sous-shell est que nous devons en extraire des données. Je montre une solution qui ne change pas l'état à la fin, avecread
. (Cela fonctionne dans les shells POSIX, mais pas IIRC dans le shell Bourne, car il s'exécuteraitread
dans un sous-shell à cause du document here.) Utiliser<<<
as dans vous répondez est une variante qui fonctionne uniquement dans ksh / bash / zsh.user/my_folder/[this_is_my_file]*
? Ce que j'obtiens quand je suis ces étapes est[this_is_my_file]*
/
.Je voulais voir une
awk
réponse, alors en voici une:la source
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
Le moyen le plus simple (pour les shells avec <<<) est:
Utiliser une variable temporelle
$a
au lieu de$_
parce qu'un shell se plaint.Dans un script complet:
Aucun IFS ne change, pas de problème avec
set -f
(extension de nom de chemin) Aucune modification des paramètres de position ("$ @").Pour une solution portable à tous les shells (oui, tous les POSIX inclus) sans changer d’IFS ou
set -f
, utilisez l’équivalent heredoc (un peu plus complexe):Comprenez que cette solution (à la fois ici-doc et l'utilisation de
<<<
, supprimera toutes les nouvelles lignes qui suivent.Et cela est conçu pour un contenu variable "one liner". Les
solutions pour les multilignes sont possibles mais nécessitent des constructions plus complexes.
Une solution très simple est possible dans la version 4.4 de bash
Il n'y a pas d'équivalent pour les shells POSIX, car de nombreux shells POSIX n'ont pas de tableaux.
Pour les shells qui ont des tableaux peuvent être aussi simples que:
(testé avec attsh, lksh, mksh, ksh et bash)
Mais avec beaucoup de tuyauterie supplémentaire pour conserver et réinitialiser les variables et les options:
Dans zsh, les tableaux commencent par 1 et ne divisent pas la chaîne par défaut.
Il faut donc faire quelques changements pour que cela fonctionne dans zsh.
la source
read
sont simples tant que OP ne veut pas extraire les 76ème et 127ème éléments d'une longue chaîne ...readarray
pourrait être plus facile à utiliser dans cette situation.Avec
zsh
vous pouvez diviser la chaîne (sur_
) en un tableau:puis accédez à chacun des éléments via un index de tableau:
Gardez à l'esprit que dans
zsh
(contrairement àksh
/bash
) les index de tableau commencent à 1 .la source
set -f
avertissement à la première solution. ... des astérisques*
peut-être?set -f
? Je n'utilise pasread
/IFS
. Essayez mes solutions avec une ficelle*_*_*
ou quelque chose comme ça ...Une solution python est-elle autorisée?
la source
Un autre exemple awk; plus simple à comprendre.
Peut être utilisé avec des variables aussi.
Supposons:
this_str = "one_two_three_four_five"
Alors les travaux suivants fonctionnent:
A = `echo $ {this_str} | awk -F_ '{print $ 1}' '
B = `echo $ {this_str} | awk -F_ '{print $ 2}' '
C = `echo $ {this_str} | awk -F_ '{print $ 3}' `
... et ainsi de suite ...
la source