Je souhaite supprimer la dernière colonne dun fichier txt, alors que je ne sais pas quel est le numéro de colonne est. Comment pourrais-je faire cela?
Exemple:
Entrée:
1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222
Et je veux que ma sortie soit :
1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Commentaires
Réponse
Avec awk
:
awk "NF{NF-=1};1" <in >out
ou:
awk "NF{NF--};1" <in >out
ou:
awk "NF{--NF};1" <in >out
Bien que cela ressemble à du vaudou, cela fonctionne. Il y a trois parties dans chacune de ces commandes awk.
La première est NF
, qui est une condition préalable pour la deuxième partie. NF
est une variable contenant le nombre de champs dans une ligne. Dans AWK, les choses sont vraies si elles « ne sont pas 0 ou une chaîne vide ""
. Par conséquent, la deuxième partie (où NF
est décrémentée) ne se produit que si NF
nest pas 0.
La deuxième partie (soit NF-=1
ou --NF
) est juste en soustrayant un de la variable NF
. Cela empêche le dernier champ dêtre imprimé, car lorsque vous modifiez un champ (en supprimant le dernier champ dans ce cas), awk
reconstruisez $0
, concaténez tous les champs séparés par un espace par défaut . $0
ne contenait plus le dernier champ.
La dernière partie est 1
. Ce nest pas magique, cest juste utilisé comme une expression qui signifie true
. Si une expression awk
prend la valeur true sans aucune action associée, awk
laction par défaut est print $0
.
Commentaires
- @JJoao: Ah, merci, jai oublié
--
. Une note, actuellement, vous avez besoin de;1
pour être compatible POSIX. - Mon instinct initial serait dutiliser une boucle for, mais cest beaucoup plus concis et intelligent.
- Il est ‘ de noter que si vous ‘ utilisez un séparateur autre que celui par défaut, vous ‘ ll faudra faire quelques changements. En supposant que
,
est votre délimiteur:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
- Leffet de la décrémentation de NF est un comportement non défini par POSIX – vous obtiendrez sortie différente selon le awk que vous ‘ exécutez. Certains awks supprimeront le dernier champ comme vous le souhaitez, certains ne feront rien du tout et dautres pourraient signaler une erreur de syntaxe ou autre chose.
Réponse
Utilisation de grep
avec PCRE:
$ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Utilisation de GNU sed
:
$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Commentaires
- @ramin Bien sûr. .Pouvez-vous la poser en tant que une nouvelle question (voici comment ce site fonctionne) 🙂
- @ramin Vous en donne-t-il une restriction de temps ou un avertissement?
- cela dit que cest hors de question!
- @ramin Ok .. laissez-moi contacter un administrateur, il pourra peut-être vous aider. btw avez-vous vérifié un ancien QA concernant votre question? cest une possibilité que la question soit déjà posée et répondue ..
- Ne ‘ t poser des questions super basiques comme » comment puis-je renommer un nom de fichier sous Linux « . Utilisez Google.
Réponse
Utilisation de Perl:
perl -lane "$,=" ";pop(@F);print(@F)" in
Utilisation de rev
+ cut
:
rev in | cut -d " " -f 2- | rev
Réponse
Utilisation de GNU sed:
sed -r "s/\s+\S+$//" input.txt
Plus généralement, celui-ci fonctionne avec BSD sed sous OSX, ainsi quavec GNU sed:
sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt
Answer
Si le délimiteur est toujours un seul caractère (donc deux délimiteurs consécutifs ou plus désignent des champs vides), vous pouvez head
juste la première ligne de votre fichier dentrée, compter les délimiteurs ( n
délimiteurs signifie que le nombre de champs est n+1
) puis utilisez cut
pour imprimer à partir de 1
st champ jusquau n
ième champ (avant-dernier), par exemple avec une entrée délimitée par des tabulations:
n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile
ou par ex.avec un fichier csv :
n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile
Je « lancerai quelques benchmarks plus tard si jai le temps mais avec une énorme contribution je pense que ceci La solution devrait être plus rapide que les autres solutions qui utilisent regex car celle-ci effectue un traitement minimal sur la première ligne pour obtenir le nombre de champs, puis utilise cut
qui est optimisé pour ce travail.
Réponse
De manière portable, vous pouvez utiliser lun ou lautre de ces éléments:
sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file
Réponse
Utilisation de vim:
Ouvrez le fichier dans vim
vim <filename>
Aller à la première ligne, juste au cas où le curseur serait placé ailleurs.
gg
Créez une macro nommée « q » qq
, qui va à larrière de la ligne courante $
, puis revient au dernier espace F
(F majuscule, suivi de SPACE littéral) puis supprimer de la position actuelle jusquà la fin de la ligne D
allez à la ligne suivante j
et arrêtez lenregistrement de la macro avec q
.
qq$F Djq
Nous pouvons maintenant répéter notre macro avec @q
pour chaque ligne.
Nous pouvons également appuyer sur @@
pour répéter la dernière macro ou même plus facilement:
99@q
pour répéter la macro 99 fois.
Remarque: Le nombre ne doit pas correspondre exactement aux lignes.
Réponse
Pour les personnes qui ont un problème similaire mais avec des séparateurs de champs différents, ceci awk
conservera correctement le séparateur de champ:
$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar
cut
sonne comme loutil pour le travail.