Je voudrais supprimer tous les espaces et tabulations de début et de fin de chaque ligne dans une sortie.
Existe-t-il un outil simple comme trim
Je pourrais diriger ma sortie vers?
Exemple de fichier:
test space at back test space at front TAB at end TAB at front sequence of some space in the middle some empty lines with differing TABS and spaces: test space at both ends
Commentaires
- À quiconque cherche ici une solution pour supprimer les sauts de ligne, cest un problème différent. Par définition, une nouvelle ligne crée une nouvelle ligne de texte. Par conséquent, une ligne de texte ne peut pas contenir de nouvelle ligne. La question que vous souhaitez poser est de savoir comment supprimer une nouvelle ligne au début ou à la fin dune chaîne: stackoverflow.com/questions/369758 , ou comment supprimer un espace vide lignes ou lignes qui ne sont que des espaces: serverfault.com/questions/252921
Réponse
awk "{$1=$1;print}"
ou plus court:
awk "{$1=$1};1"
Réduirait le début et espace de fin ou caractères de tabulation 1 et aussi séquences de tabulations et des espaces dans un seul espace.
Cela fonctionne car lorsque vous attribuez quelque chose à lun des champs , awk
reconstruit tout lenregistrement (tel quimprimé par print
) en joignant tous les champs ($1
, …, $NF
) avec OFS
(espace par défaut).
1 (et éventuellement un autre caractère vide s en fonction de la langue et de la awk
implémentation)
Commentaires
- Point-virgule allumé le deuxième exemple est superflu. Peut utiliser:
awk '{$1=$1}1'
- @Brian, non, le
;
est requis dans la syntaxe awk standard - Intéressant … Aucun point-virgule nest pris en charge par gawk, mawk et OS X ‘ s awk. (Au moins pour mes versions (1.2, 4.1.1 et 20070501, respectivement)
- La seule chose que je naime pas ‘ dans cette approche, cest que vous perdre les espaces répétitifs dans la ligne. Par exemple,
echo -e 'foo \t bar' | awk '{$1=$1};1'
-
echo ' hello ' | xargs
Réponse
La commande peut être condensée comme ceci si vous « utilisez GNU sed
:
$ sed "s/^[ \t]*//;s/[ \t]*$//" < file
Exemple
Voici la commande ci-dessus en action.
$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" blahblah
Vous pouvez utiliser hexdump
pour confirmer que la commande sed
supprime correctement les caractères souhaités.
$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" | hexdump -C 00000000 62 6c 61 68 62 6c 61 68 0a |blahblah.| 00000009
Classes de caractères
Vous pouvez également utiliser des noms de classes de caractères au lieu de lister littéralement les ensembles comme ceci, [ \t]
:
$ sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" < file
Exemple
$ echo -e " \t blahblah \t " | sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//"
La plupart des outils GNU qui utilisent l’expression régulière ssions (regex) supportent ces classes (ici avec leur équivalent dans la locale C typique dun système ASCII (et là uniquement)).
[[:alnum:]] - [A-Za-z0-9] Alphanumeric characters [[:alpha:]] - [A-Za-z] Alphabetic characters [[:blank:]] - [ \t] Space or tab characters only [[:cntrl:]] - [\x00-\x1F\x7F] Control characters [[:digit:]] - [0-9] Numeric characters [[:graph:]] - [!-~] Printable and visible characters [[:lower:]] - [a-z] Lower-case alphabetic characters [[:print:]] - [ -~] Printable (non-Control) characters [[:punct:]] - [!-/:-@[-`{-~] Punctuation characters [[:space:]] - [ \t\v\f\n\r] All whitespace chars [[:upper:]] - [A-Z] Upper-case alphabetic characters [[:xdigit:]] - [0-9a-fA-F] Hexadecimal digit characters
Utilisation ceux-ci au lieu de jeux littéraux semblent toujours être une perte despace, mais si vous êtes préoccupé par le fait que votre code soit portable ou que vous ayez à gérer des jeux de caractères alternatifs (pensez à linternational), vous voudrez probablement utiliser les noms de classe à la place .
Références
Commentaires
- Notez que
[[:space:]]
nest pas équivalent à[ \t]
dans le cas général (unicode, etc.).[[:space:]]
sera probablement beaucoup plus lent (car il y a beaucoup plus de types despaces blancs en Unicode que simplement' '
et'\t'
). Même chose pour tous les autres. -
sed 's/^[ \t]*//'
nest pas portable. Finalement, POSIX exige même que pour supprimer une séquence de caractères despace, de barre oblique inverse ou det
, et que ‘ est ce que GNUsed
le fait également lorsquePOSIXLY_CORRECT
est dans lenvironnement. - Que faire si je veux couper les caractères de nouvelle ligne? ‘ \ n \ n text \ n \ n ‘
- Jaime la solution sed en raison de labsence de dautres effets secondaires comme dans la solution awk. La première variante ne fonctionne pas lorsque je lai essayé en bash sur OSX jsut maintenant, mais la version de la classe de caractères fonctionne:
sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
- @EugeneBiryukov voir mon commentaire sur le message dorigine
Réponse
xargs sans arguments font cela.
Exemple:
trimmed_string=$(echo "no_trimmed_string" | xargs)
Commentaires
- Cela réduit également plusieurs espaces dans une ligne, qui na pas été demandée dans la question
- @roaima – true mais la réponse acceptée serre également les espaces (ce qui na pas été demandé dans la question). Je pense que le vrai problème ici est que
xargs
échouera si lentrée contient des barres obliques inverses et des guillemets simples. - @don_crissti qui ne ‘ t signifie que la réponse acceptée répond correctement à la question posée, cependant. Mais dans ce cas ici, il nétait pas ‘ t marqué comme une mise en garde alors que dans la réponse acceptée cétait le cas. Jespère que jai ‘ souligné le fait au cas où cela ‘ serait pertinent pour un futur lecteur.
- Cela aussi coupures sur les guillemets simples, les guillemets doubles, les caractères anti-slash Il exécute également une ou plusieurs invocations
echo
. Certaines implémentations décho traiteront également des options et / ou des barres obliques inverses … Cela ne fonctionne également que pour une entrée sur une seule ligne.
Answer
Comme suggéré par Stéphane Chazelas dans la réponse acceptée, vous pouvez maintenant
créer un script /usr/local/bin/trim
:
#!/bin/bash awk "{$1=$1};1"
et donnez à ce fichier des droits exécutables:
chmod +x /usr/local/bin/trim
Vous pouvez maintenant transmettre chaque sortie à trim
par exemple:
cat file | trim
(pour les commentaires ci-dessous: jai déjà utilisé ceci: while read i; do echo "$i"; done
qui fonctionne également très bien, mais est moins performant)
Commentaires
- Bonne chance si votre fichier est volumineux et / ou contient des contre-obliques.
- @don_crissti: pourriez-vous commenter un peu plus?, Quelle solution convient mieux aux fichiers volumineux, et comment pourrais-je modifier ma solution si le fichier contenait des barres obliques inverses?
- Vous ‘ devrez utiliser
while read -r line
pour conserver les contre-obliques et même dans ce cas … . En ce qui concerne les fichiers / vitesse énormes, vous avez vraiment choisi la pire solution. Je ne ‘ ne pense pas que ‘ s quelque chose de pire là-bas. Voir les réponses sur Pourquoi utiliser une boucle shell pour traiter du texte est une mauvaise pratique? y compris mon commentaire sur la dernière réponse où jai ajouté un lien vers un benchmark de vitesse. Les réponsessed
ici sont parfaitement correctes IMO et bien meilleures queread
. - Vous pouvez également ajouter un alias dans / etc / profile (ou votre alias ~ / .bashrc ou ~ / .zshrc etc …) trim = » awk ‘ { \ $ 1 = \ $ 1}; 1 ‘ »
- Pas besoin de
bash
, vous pouvez le créer#! /usr/bin/awk -f
{$1=$1};1
. (attention cependant aux noms de fichiers contenant=
caractères)
Réponse
Si vous stockez des lignes en tant que variables, vous pouvez utiliser bash pour faire le travail:
supprimer les espaces au début dune chaîne:
shopt -s extglob echo ${text##+([[:space:]])}
supprimer les espaces de fin dune chaîne:
shopt -s extglob echo ${text%%+([[:space:]])}
supprimer tous les espaces dune chaîne:
echo ${text//[[:space:]]}
Commentaires
- Supprimer tous les espaces dune chaîne nest pas la même chose que supprimer les espaces de début et de fin (comme dans la question).
- De loin la meilleure solution – elle ne nécessite que des fonctions intégrées bash et aucune fourche de processus externe.
- Nice. Les scripts sexécutent BEAUCOUP plus vite sils nont ‘ pas à intégrer des programmes extérieurs (tels que awk ou sed). Cela fonctionne également avec les versions » modernes » (93u +) de ksh.
Réponse
sed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//"
Si vous « lisez une ligne dans une variable shell, read
fait déjà cela sauf indication contraire .
Commentaires
- +1 pour
read
. Donc, si vous pointez vers pendant la lecture, cela fonctionne:cat file | while read i; do echo $i; done
- @rubo sauf que dans votre exemple, la variable sans guillemets est également retraitée par le shell. Utilisez
echo "$i"
pour voir le véritable effet deread
Réponse
Pour supprimer tous les espaces de début et de fin dune ligne donnée grâce à un outil « piped », je peux identifier 3 différents des voies qui ne sont pas tout à fait équivalentes. Ces différences concernent les espaces entre les mots de la ligne dentrée. En fonction du b attendu ehaviour, vous ferez votre choix.
Exemples
Pour expliquer les différences, considérons cette ligne dentrée factice:
" \t A \tB\tC \t "
tr
$ echo -e " \t A \tB\tC \t " | tr -d "[:blank:]" ABC
tr
est en réalité une commande simple. Dans ce cas, il supprime tout espace ou caractère de tabulation.
awk
$ echo -e " \t A \tB\tC \t " | awk "{$1=$1};1" A B C
awk
supprime les espaces de début et de fin et réduit à un seul espace tous les espaces entre les mots.
sed
$ echo -e " \t A \tB\tC \t " | sed "s/^[ \t]*//;s/[ \t]*$//" A B C
Dans ce cas, sed
supprime les espaces de début et de fin sans toucher aux espaces entre les mots.
Remarque:
Dans le cas dun mot par ligne, tr
fait le travail.
Commentaires
- Aucun de ces éléments ne supprime les nouvelles lignes de fin / de tête
- +1 pour une liste de solutions avec leur sortie (parfois inattendue).
- @ user61382 cest plutôt tard, mais voyez mon commentaire sur le message original.
- @highmaintenance: utilisez
[:space:]
, au lieu de [: blank:], pour la commandetr
, comme:... | tr -d [:space:]
, pour supprimer également les nouvelles lignes. (voir:man tr
)
Réponse
sed est un excellent outil pour cela:
# substitute ("s/") sed "s/^[[:blank:]]*//; # parts of lines that start ("^") with a space/tab s/[[:blank:]]*$//" # or end ("$") with a space/tab # with nothing (/)
Vous pouvez lutiliser pour votre cas soit dans le texte, par exemple
<file sed -e "s/^[[...
ou en agissant dessus « en ligne » si votre sed
est celui de GNU:
sed -i "s/..." file
mais changer la source de cette façon est « dangereux » car il peut être irrécupérable quand cela ne fonctionne pas correctement (ou même quand cela fonctionne!), alors sauvegardez dabord (ou utilisez -i.bak
qui a également lavantage dêtre portable sur certains BSD sed
s)!
Réponse
Une réponse que vous pouvez comprendre en un coup dœil:
#!/usr/bin/env python3 import sys for line in sys.stdin: print(line.strip())
Bonus: remplacez str.strip([chars])
avec des caractères arbitraires pour couper ou utiliser .lstrip()
ou .rstrip()
selon les besoins.
Comme rubo77 « sa nswer , enregistrez en tant que script /usr/local/bin/trim
et accordez les autorisations avec chmod +x
.
Réponse
Si la chaîne que lon essaie de couper est courte et continue / contiguë, on peut simplement la passer en paramètre à nimporte quelle fonction bash:
trim(){ echo $@ } a=" some random string " echo ">>`trim $a`<<" Output >>some random string<<
Answer
Jai écrit cette fonction shell en utilisant awk
awkcliptor(){ awk -e "BEGIN{ RS="^$" } {gsub(/^[\n\t ]*|[\n\t ]*$/,"");print ;exit}" "$1" ; }
BEGIN{ RS="^$" }
:
au début avant de commencer lanalyse set record
separator to none cest-à-dire traiter toute lentrée comme
un seul enregistrement
gsub(this,that)
:
remplacer cette expression rationnelle par cette chaîne
/^[\n\t ]*|[\n\t ]*$/
:
de cette chaîne attraper tout espace avant nouvelle ligne et toute classe de tabulation
ou publier un espace de nouvelle ligne et une classe de tabulation et les remplacer par
chaîne vide
print;exit
: puis imprimez et quittez
"$1"
:
et passez le premier argument de la fonction à be
process by awk
comment utiliser:
copier le code ci-dessus, coller dans le shell, puis entrer pour
définir la fonction.
alors vous pouvez utiliser awkcliptor comme commande avec le premier argument comme fichier dentrée
exemple dutilisation:
echo " ggggg " > a_file awkcliptor a_file
sortie:
ggggg
ou
echo -e "\n ggggg \n\n "|awkcliptor
sortie:
ggggg
Commentaires
- Pouvez-vous expliquer la différence uniquement avec
awk '{$1=$1};1'
?
Réponse
Pour ceux dentre nous qui nont pas assez despace dans le cerveau pour se souvenir de la syntaxe sed obscure, inversez simplement la chaîne , coupez le premier champ avec un délimiteur despace et inversez-le à nouveau.
cat file | rev | cut -d" " -f1 | rev
Commentaires
- Cela ne fonctionne que sil ny a pas plus dun espace devant chaque ligne et pas plus dun mot dans une ligne.
Réponse
trimpy () { python3 -c "import sys for line in sys.stdin: print(line.strip())" } trimsed () { gsed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" } trimzsh () { local out="$(</dev/stdin)" [[ "$out" =~ "^\s*(.*\S)\s*$" ]] && out="$match[1]" || out="" print -nr -- "$out" } # example usage echo " hi " | trimpy
Bonus: remplacez str.strip([chars])
par des caractères arbitraires pour couper ou utiliser ou .rstrip()
selon les besoins.
Réponse
La commande translate fonctionnerait
cat file | tr -d [:blank:]
Commentaires
- Cette commande nest pas correcte car elle supprime tous les espaces du fichier, pas seulement les espaces de début / fin.
- @BrianRedbeard Vous avez raison. Cest toujours une réponse utile pour une chaîne monolithique, sans espaces.
Réponse
pour lexemple bash:
alias trim="awk "{\$1=\$1};1""
utilisation:
echo -e " hello\t\tkitty " | trim | hexdump -C
résultat:
00000000 68 65 6c 6c 6f 20 6b 69 74 74 79 0a |hello kitty.| 0000000c
Commentaires
- La réponse
awk '{$1=$1};1'
a été donnée il y a longtemps. Lidée den faire un alias a été suggérée dans un commentaire il y a presque aussi longtemps. Oui, vous êtes autorisé à prendre le commentaire de quelquun dautre et à en faire une réponse. Mais si vous le faites, vous devriez donner du crédit aux personnes qui ont posté lidée avant vous. Et cest une extension si triviale de la réponse acceptée que cela ne vaut pas vraiment la peine. - Lidée était de créer un alias. Je nai ‘ pas vu cette réponse auparavant.
- et deuxième chose de la pile: » Merci pour vos commentaires! Les votes exprimés par ceux qui ont moins de 15 points de réputation sont enregistrés, mais ne modifient pas le score affiché publiquement. »