Comment supprimer une ligne si plus longue que XY?

22

Comment puis-je supprimer une ligne si elle est plus longue que par exemple: 2048 caractères?

LanceBaynes
la source
Insistez-vous pour utiliser sed? C'est facile, par exemple en python. Et sans doute encore plus facile en perl. Bien que la question ne soit pas terriblement bien définie. Copiez un fichier, supprimez toutes les lignes de plus de 2048, ou autre chose?
Faheem Mitha

Réponses:

23
sed '/^.\{2048\}./d' input.txt > output.txt
forcefsck
la source
3
Je reçois le message d'erreur sed: 1: "/^.\{2048\}..*/d": RE error: invalid repetition count(s)(Mac OS X)
wedi
1
@wedi vous voulez probablement installer la version GNU au lieu de la version BSD livrée avec Mac. C'est facile avec l'infusion
Freedom_Ben
La question dit "si plus long que XY (par exemple, 2048 caractères)". Ensuite, il doit être> 2048 et non => 2048
ajcg
1
@ajcg, c'est> 2048. Notez qu'il y a une période supplémentaire à la fin de l'expression régulière pour correspondre au 2049e caractère.
forcefsck
@forcefsck et ce ne serait pas mieux si vous l'enlevez "^"? (avec votre commande, vous supprimez uniquement les lignes qui "commencent par XYZ", mais si XYZ se trouve dans une autre partie de la ligne, il ne la supprime pas)
ajcg
7

Voici une solution qui supprime les lignes de 2049 caractères ou plus:

sed -E '/.{2049}/d' <file.in >file.out

L'expression /.{2049}/dcorrespondra à toute ligne contenant au moins 2049 caractères et les supprimera de l'entrée, ne produisant qu'une ligne plus courte sur la sortie.

Avec awk, lignes d'impression d'une longueur égale ou inférieure à 2048:

awk 'length <= 2048' <file.in >file.out

Imitant la sedsolution littéralement avec awk:

awk 'length >= 2049 { next } { print }' <file.in >file.out
Kusalananda
la source
1
Je reçois le message d'erreur sed: 1: "/^.\{400,\}$/d": RE error: invalid repetition count(s)(Mac OS X)
wedi
1
@wedi Maintenant mis à jour et testé sur macOS Mojave.
Kusalananda
2

Quelque chose comme ça devrait fonctionner en Python.

of = open("orig")
nf = open("new",'w')
for line in of:         
    if len(line) < 2048:
        nf.write(line)
of.close()
nf.close()
Faheem Mitha
la source
1
Personnellement, @Faheem, je préfère votre réponse. La raison en est qu'il m'a été très facile de le transformer en «supprimer toutes les lignes inférieures à x». Je n'utilise pas Python tout le temps, mais quand je le fais, je pense toujours que je devrais bien l'apprendre.
ixtmixilix
@ixtmixilix: Oui, l'utilisation d'un langage complet comme Python est assez flexible. Merci pour le commentaire.
Faheem Mitha
2
perl -lne "length < 2048 && print" infile > outfile
MaratC
la source
+1 Le -ln'est cependant pas nécessaire.
Joseph R.
Ça ne marche pas pour moi. Perl v5.16.2. Warning: Use of "length" without parentheses is ambiguous at -e line 1. Unterminated <> operator at -e line 1.
wedi
Vous pouvez essayer length($_) > 2048 && print. lengthest un raccourci de length($_)toute façon.
MaratC
0

Les réponses ci-dessus ne fonctionnent pas pour moi sur Mac OS X 10.9.5.

Le code suivant fonctionne:

sed '/.\{2048\}/d'.

Bien que non demandé, mais fourni à titre de référence, l'inverse peut être obtenu avec le code suivant:

sed '/.\{2048\}/!d'.

wedi
la source
lol, mais sed: 1: "/.\{2048\}/d": RE error: invalid repetition count(s)( Mac OS X, 10.10.4)
alex gray
Ah. J'ai installé la version GNU au lieu de la version BSD fournie avec Mac comme @Freedom_Ben suggéré ci-dessus. Mais Kusalananda a trouvé le commutateur pour activer l'expression régulière étendue. Vous devriez donc aller avec sa solution si vous avez toujours ce problème. ;)
wedi
0

Avec gnu-sed, vous pouvez utiliser l'indicateur -r, pour éviter de taper les barres obliques inverses et une virgule, pour définir un intervalle ouvert:

sed -r  "/.{2049,}/d" input.txt > output.txt

avec:

  • x {2049} signifiant exactement 2049 xs
  • x {2049,3072} signifiant de 2049 à 3072 xs
  • x {2049,} signifiant au moins 2049 xs
  • x {, 2049} signifiant au plus 2049 xs

Pour les intervalles, pour ne pas correspondre à des motifs plus grands, vous auriez besoin d'ancrages de ligne comme

sed -r  "/^.{32,64}$/d" input.txt > output.txt 
Utilisateur inconnu
la source