Il existe de nombreuses façons de remplacer des caractères dans une variable.
Le moyen le plus court que j'ai découvert est tr
jusqu'à présent:
OUTPUT=a\'b\"c\`d_123and_a_lot_more
OUTPUT=$(echo "$OUTPUT"|tr -d "'\`\"")
echo $OUTPUT
Y at-il un moyen plus rapide? Et est-ce sûr pour les citations comme '
, "
et `lui-même?
tr
. Le PE de BASH est bon mais tr est beaucoup plus rapide dans ce cas. par exemple,echo "$OUTPUT" | tr -dc '[[:alpha:]]'
puisque vous ne voulez avoir que des caractères alphanumériquesecho "$OUTPUT"
. Ou mieux:printf "%s\n" "$OUTPUT"
. (Que se passe-t-il quandOUTPUT="-n"
?)Réponses:
Voyons voir. Le plus court que je puisse proposer est un ajustement de votre
tr
solution:D'autres alternatives incluent la substitution de variables déjà mentionnée qui peut être plus courte que celle illustrée jusqu'à présent:
Et
sed
bien sûr, cela est plus long en termes de caractères:Je ne sais pas si vous voulez dire la durée la plus courte ou en termes de temps pris. En termes de longueur, ces deux sont aussi courts que possible (ou comme je peux l'obtenir de toute façon) quand il s'agit de supprimer ces caractères spécifiques. Alors, quel est le plus rapide? J'ai testé en définissant la
OUTPUT
variable sur ce que vous aviez dans votre exemple, mais j'ai répété plusieurs dizaines de fois:Comme vous pouvez le voir, le
tr
est clairement le plus rapide, suivi de prèssed
. De plus, il semble que l'utilisationecho
soit en fait légèrement plus rapide que l'utilisation de<<<
:Étant donné que la différence est minuscule, j'ai effectué les tests ci-dessus 10 fois pour chacun des deux et il s'avère que le plus rapide est en effet celui avec lequel vous avez dû commencer:
Cependant, cela change lorsque vous prenez en compte les frais généraux d'affectation à une variable, ici, l'utilisation
tr
est légèrement plus lente que le remplacement simple:Donc, en conclusion, lorsque vous souhaitez simplement afficher les résultats, utilisez
tr
mais si vous souhaitez réaffecter à une variable, l'utilisation des fonctionnalités de manipulation de chaîne du shell est plus rapide car elles évitent la surcharge d'exécution d'un sous-shell séparé.la source
OUTPUT
, vous devrez tenir compte de la surcharge de sous-shell de substitution de commandes impliquée danstr
et dessed
solutionsOUTPUT="${OUTPUT//[`\"\']/}"
n'implique pas de substitution de commandeVous pouvez utiliser la substitution de variable :
Utilisez cette syntaxe:
${parameter//pattern/string}
pour remplacer toutes les occurrences du modèle par la chaîne.la source
echo ${OUTPUT//[`\"\']/x}
donneaxbxcxa
En bash ou zsh c'est:
Notez que
${VAR//PATTERN/}
supprime toutes les instances du modèle. Pour plus d'informations sur l' expansion des paramètres bashCette solution devrait être plus rapide pour les chaînes courtes car elle n'implique pas l'exécution de programmes externes. Cependant, pour les très longues chaînes, l'inverse est vrai - il est préférable d'utiliser un outil dédié pour les opérations de texte, par exemple:
la source
tr
c'est plus rapide. Les expressions régulières et les globes sont chers, et bien qu'il n'y ait pas de programme externe ici, bash sera toujours plus lent que quelque chose commetr
.tr
gagne (voir ma réponse). Je suis d'accord que cela dépendra de nombreux facteurs, mais c'est exactement pourquoi vous ne pouvez pas dire lequel gagne sans le tester.Si, par hasard, vous essayez simplement de gérer des devis pour réutiliser la coque, vous pouvez le faire sans les supprimer, et c'est aussi simple que cela:
Ce shell de fonction cite tout tableau arg que vous lui donnez et incrémente sa sortie par argument itérable.
Le voici avec quelques arguments:
PRODUCTION
Cette sortie est celle à partir de
dash
laquelle les guillemets simples sont généralement sécurisés'"'"'
.bash
ferait'\''
.Le remplacement d'une sélection d'octets simples, non blancs et non nuls par un autre octet unique peut probablement se faire le plus rapidement dans n'importe quel shell POSIX avec
$IFS
et$*
.PRODUCTION
Là je l'ai juste
printf
pour que vous puissiez le voir, mais bien sûr, si j'avais fait:... plutôt que la valeur de la
printf
commande$var
serait ce que vous voyez dans la sortie.Lorsque
set -f
j'ordonne au shell de ne pas glob - au cas où la chaîne contient des caractères qui pourraient être interprétés comme des modèles glob. Je le fais parce que l'analyseur de shells étend les modèles globaux après avoir effectué la division du champ sur les variables. le globbing peut être réactivé commeset +f
. En général - dans les scripts - je trouve utile de définir mon bang comme:Et puis pour activer explicitement le globbing avec
set +f
sur n'importe quelle ligne je pourrais le vouloir.La division des champs se produit en fonction des caractères dans
$IFS
.Il existe deux types de
$IFS
valeurs: les$IFS
espaces blancs et$IFS
non blancs.$IFS
les espaces délimités par des espaces (espace, tabulation, nouvelle ligne) sont spécifiés pour être éliminés par séquence vers un seul champ (ou aucun du tout s'ils ne précèdent pas autre chose) - donc ...Mais tous les autres sont spécifiés pour évaluer un seul champ par occurrence - ils ne sont pas tronqués.
Toutes les extensions de variables sont, par défaut,
$IFS
des tableaux de données délimités - elles se répartissent en champs séparés selon$IFS
. Lorsque vous en"
citez une, vous remplacez cette propriété de tableau et l'évaluez comme une chaîne unique.Alors quand je fais ...
Je mets le tableau d'arguments du shell sur les nombreux
$IFS
champs délimités générés par$var
l'expansion de. Lorsqu'elle est développée, ses valeurs constitutives pour les caractères contenus dans$IFS
sont perdues - ce ne sont plus que des séparateurs de champs - elles le sont\0NUL
."$*"
- comme les autres extensions de variable entre guillemets doubles - remplace également les qualités de séparation de champ de$IFS
. Mais, en plus , il substitue le premier octet dans$IFS
pour chaque champ délimité dans"$@"
. Parce que"
a été la première valeur dans$IFS
tous les délimiteurs suivantes deviennent"
en"$*"
. Et le"
besoin n'est pas là non plus$IFS
lorsque vous le divisez. Vous pouvez modifier complètement$IFS
aprèsset -- $args
une autre valeur et son nouveau premier octet apparaîtra alors pour les délimiteurs de champ dans"$*"
. De plus, vous pouvez en supprimer toutes les traces comme:PRODUCTION
la source
tr
dans n'importe quel shell, mais la différence est incertaine dansbash
le${var//$c/$newc/}
cas. Je m'attends même à ce que ce soit plus rapide par une certaine marge, mais je ne m'inquiète généralement pas à ce sujet parce que pour ce genre de choses que j'utilise toujoursdash
- qui est plus rapide par ordre de grandeur en général à tous égards. Et donc c'est difficile à comparer.bash
-time (IFS=\"\'`; set -- $var; printf %s "$*")
et lestime (var=${var//\'`/\"/})
deux donnent des0.0000s
résultats pour tous les domaines. Suis-je en train de faire quelque chose de mal, pensez-vous? Il doit y avoir une barre oblique inverse avant la citation inverse, mais je ne sais pas comment mettre une citation inverse dans un champ de code de commentaire.