2012-12-09 1 views
2

Mon fichier texte est trié par ordre alphabétique. Je veux déterminer si chaque ligne est contenue dans la ligne suivante, et si oui, supprimer le premier des deux. Ainsi, par exemple, si je devais ...sed: comment déterminer si la ligne 1 est contenue dans la ligne 2

car 
car and trailer 
train 

... Je veux finir avec ...

car and trailer 
train 

J'ai trouvé la page "sed one-liners" (s) , qui a le code pour rechercher des lignes en double:

sed '$! N; /^(.*)\n\1$/!P; D '

... et je pensais que la suppression de^ferait l'affaire, mais ce n'était pas le cas.

(Il serait également agréable de le faire avec des lignes non-consécutives, mais mes fichiers courir à des milliers de lignes, et il serait probablement prendre quelques heures de script, ou jours, à courir.)

+0

Ignorer le cas serait un plus. – user1889034

+0

Comme votre RE contient un signe '$' à la fin, cela signifie que * line1 correspond exactement à line2 * not * line1 est contenue dans line2 * –

+0

Comme une suggestion connexe, pourquoi ne pas simplement écrire plusieurs lignes python pour terminer cette tâche ? – sleepsort

Répondre

2

L'original commande

sed '$!N; /^\(.*\)\n\1$/!P; D' 

Recherche une correspondance de ligne exacte. Comme vous voulez vérifier si la première ligne est contenue dans le second, vous devez ajouter quelques jokers:

sed '$!N; /^\(.*\)\n.*\1.*$/!P; D' 

devrait le faire.

+0

Non: avec mon exemple, 'echo $ 'cat \ ncat et dog \ nhouse \ nmoney \ ngold et money \ n'', cette' house' d'impression aussi. –

+0

Pouah. Merci pour les modifications les gars. Sur mon téléphone, j'ai simplement copié le cmd de l'OP et je n'ai pas repéré les accolades manquantes. :) – TheRuss

+0

@ F.Hauri maison devrait imprimer que la ligne suivante ne contient pas de maison. – TheRuss

0

Vous avez dit:

Il serait également agréable de le faire avec des lignes non consécutives.

Voici un script bash pour supprimer toutes les lignes plus courtes contenues dans une autre ligne, pas nécessairement consécutive, insensible à la casse:

#!/bin/bash 
# sed with I and Q are gnu extensions: 
cat test.txt | while read line; do 
    echo Searching for: $line 
    sed -n "/.$line/IQ99;/$line./IQ99" test.txt # or grep -i 
    if [ $? -eq 99 ]; then 
     echo Removing: $line 
     sed -i "/^$line$/d" test.txt 
    fi 
done 

Test:

$ cat test.txt 
Boat 
Car 
Train and boat 
car and cat 

$ my_script 
Searching for: Boat 
Removing: Boat 
Searching for: Car 
Removing: Car 
Searching for: Train and boat 
Searching for: car and cat 

$ cat test.txt 
Train and boat 
car and cat 
+0

Ceci est très utile! Merci à tous! – user1889034

2

sed est un excellent outil pour des substitutions simples sur une seule ligne, pour toute autre utilisation, il suffit d'utiliser awk:

awk '$0 !~ prev{print prev} {prev=$0} END{print}' file 
Questions connexes