0
votes

BASH SUR LA SURTINAGE

Je me demande s'il existe un moyen facile de vérifier si une chaîne est une ultérieurement d'une autre chaîne de bash, en fait une subséquence avec une règle supplémentaire. Je vais expliquer.

Certaines échecs de "Apple" sont "APLE", "AL", "PP" et "ALE". Les sous-successions avec une règle supplémentaire, je veux obtenir sont celles qui commencent et se terminent par la même lettre que la chaîne, alors que "ANLE" et "ALE" correspond à mon désir.

J'ai fait le programme suivant : xxx

il est exécuté comme suivi: xxx

Ce programme fonctionne, mais est très lent.

Il faut toutes les lignes du fichier, modifiez-la à l'expression de Regex, puis vérifiez s'ils correspondent, puis imprimez la ligne d'origine. Sure Exemple:

L'une des lignes a le mot Google

$ La recherche devient g. * Ose * g. E (les lettres répétées deviennent pressées, une règle supplémentaire)

Nous vérifions cette expression avec le paramètre donné et si elle correspond, nous imprimons la ligne: Google

Ceci fonctionne Bien, cependant, lorsque les mots de fichier.txt devient trop gros, ce programme devient trop lent. Comment puis-je accélérer mon programme, éventuellement par des sous-séquences de correspondance plus rapides.

EDIT après une solution possible de Kamilcuk

Cette solution renvoie rapidement, Quiff, Quin, QWERTY pour la chaîne "qwertyuihgfcvbnhjk" et seulement rapide doit être retourné, il est donc presque correct, mais pas encore.


8 commentaires

Pouvez-vous poster un extrait de mots.txt et d'exemple de sorties. Je ne peux pas tester votre script, certains mots qui correspondent et ne correspondent pas à certaines intrants seraient utiles. Est apppppppple une recherchequence de Apple ? Parce que votre script le correspondre à Apple .


Si je comprends bien, il n'y a que 4 suivants valides de Apple : AE ALE singe APLE < / code>. À droite?


Oui, mais appppppppppe correspondrait également à mon programme, qui est destiné.


Och? Donc, a Pple a également suivi de Apple? Le "suivant" ne ressemble pas à la "sous-séquence" puis, plutôt comme une expansion. Donc, une sous-séquence ne fait que quelque chose qui correspond à la regex consistait en lettres d'un mot avec . * entre les lettres, fin de l'histoire?


Non, AppPPE est une pomme ultérieure parce que mon programme serre d'abord des caractères répétés. Donc Appppe devient singe et qui est ultérieur de la pomme.


Pourquoi n'utilisez-vous pas Awk pour cela?


Parce que je ne sais pas awk.


Êtes-vous toujours à la recherche de solution, faites-vous de travailler pour vous?


4 Réponses :


0
votes

bash code> n'a pas besoin d'utiliser Expr code> (un programme externe) pour une correspondance d'expression régulière; Il fournit un accès intégré à la bibliothèque de votre système.

#!/bin/bash
while read line
do
    search=$(echo "$line" | tr -s 'A-Za-z' | sed 's/./\.\*&/g;s/^\.\*//' )
    [[ $1 =~ $search ]] && echo "$line"
done


4 commentaires

Comment utiliser Grep dans mon programme?


Désolé, j'ai oublié de nourrir l'argument à Grep .


Le problème avec grep il ira simplement le contenu de 1 $ . Nous voulons sortir les lignes de mots.txt , non? Nous devrions faire la sortie de Grep la regex qu'il correspond à 1 $


Bon point. Une solution encore plus rapide, cependant, serait de faire tout cela dans un seul processus awk . Je vais voir si je peux obtenir ce droit après plusieurs tentatives infructueuses.



0
votes

Vous pouvez utiliser un motif au lieu d'une regex. Il suffit d'insérer l'astérisque après chaque lettre de chaque mot (EXCEPET la dernière lettre) et utilisez une correspondance normale de modèle.

#!/bin/bash
while read line
do
    pattern=""
    for ((i=${#line}-1 ; i>=0 ; --i)) ; do
        pattern="${line:i:1}*"$pattern
    done
    pattern=${pattern%'*'}

    if [[ "$1" == $pattern ]] ; then
        echo "$line"
    fi
done


0 commentaires

2
votes

Essayez-le comme si: xxx

testé contre: xxx

sorties: xxx

et pour set - greogdgedlqfe Il diffuse juste Google .

Si je vous comprends correctement, une "suivante" de Apple est tout ce que mathes ap * l * e .

Testé sur REPL


6 commentaires

très sympa exactement ce que je veux mettre en œuvre swype ou swiftkey


En fait, cela ne devrait pas correspondre à un * p * l * e, aucun espaces mais nécessaire pour la sortie


Petite note: le modèle Grep pour 'greogdgedlqfe' est 'gr e o g d g e d l < I> Q F E '. Je crois que la règle «supplémentaire» demandée est que le modèle soit «GR E O d g e d l q f * e '(commencez par g, fin avec e).


@Kamilcuk presque correct, j'ai édité ma question avec plus d'exemples et répondez pourquoi le vôtre est faux


Je pense qu'un changement mineur: 'grep -x "$ (<<<" 1 $ "TR -S' A-ZA-Z '| S /./&*/ G; S / * & //; S / * // 1; S / * $ // ') "mots.txt' s'adressera au qwertyuihgfcvbnhjk bug.


Il y avait une faute de frappe. Le & était censé être $ , pour supprimer le dernier. Dunno pourquoi je ne l'ai pas vu? Maintenant, il retourne rapidement pour ces 4 mots dans votre édition ....



0
votes

difficile à battre perl avec regexp.

performances

La clé de la performance consiste à éviter les processus supplémentaires supplémentaires. La plupart des solutions Bash présentées ici (à l'exception de la solution basée sur kamilcuk grep , qui n'est pas toujours correcte) nécessitera plusieurs appels sur SED, TR, etc. Perl surperformera cette solution. Même si une solution pure bash peut être mise en œuvre (à l'aide de Bash Re, des motifs), Perl est susceptible de surperformer la surperformance, lorsque la taille de la liste des mots est grande.

considère programme.pl Appl Applet < mots.txt xxx

update 1: Mise en œuvre de Perl de la solution Kamilcuk + corrective.

Je crois que possible d'utiliser l'idée de la solution à base de grep pour créer un programme PERL qui sera encore plus rapide. Il crée un seul réégycle et testez chaque mot dans le fichier de liste de mots. Je pense que cela est aussi optimal que possible avec perl. xxx


0 commentaires