web-dev-qa-db-fra.com

Remplacez plusieurs espaces par un seul en utilisant «tr» uniquement

J'ai un fichier, f1.txt:

ID     Name
1      a
2         b
3   g
6            f

Le nombre d'espaces est pas fixe. Quelle est la meilleure façon de remplacer tous les espaces blancs par un seul espace en utilisant uniquement tr?

Voici ce que j'ai jusqu'à présent:

cat f1.txt | tr -d " "

Mais la sortie est:

IDName
1a
2b
3g
6f

Mais je veux que ça ressemble à ceci:

ID Name
1 a
2 b
3 g
6 f

Veuillez essayer d'éviter sed.

77
gkmohit

Avec tr, utilisez l'option de répétition squeeze :

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

Ou vous pouvez utiliser une solution awk:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

Lorsque vous modifiez un champ dans l'enregistrement, awk rebuild $0, prend tous les champs et les concatère ensemble, séparés par OFS, qui est un espace par défaut.

Cela compressera les séquences d'espace et de tabulations (et éventuellement d'autres caractères vides en fonction des paramètres régionaux et de l'implémentation de awk) dans un espace, mais supprimera également les blancs de début et de fin de chaque ligne.

112
cuonglm

Utilisez simplement column :

column -t inputFile

Production:

ID  Name
1   a
2   b
3   g
6   f
21
polym

Si vous voulez compresser "l'espace blanc", vous voudrez utiliser les jeux de caractères prédéfinis de tr ": vide:" (onglet et espace horizontal) ou ": espace:" (espace vertical):

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

Des exemples ont été exécutés sur Red Hat 5 (GNU tr).

Dans mon cas, je voulais normaliser tous les espaces en un seul espace afin de pouvoir compter sur l'espace en tant que delmitter.

Comme le souligne le deuxième commentaire de dastrobu, j'ai raté le libellé de la page de manuel:

 -s uses the last specified SET, and occurs after translation or deletion.

Cela nous permet d'éliminer le premier tr. Kudo est à la recherche de sa patience face à ma densité.

Avant, analyser le port depuis la configuration Redis. fichier:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

Après, avec SET2 étant spécifié avec la compression:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

Production:

6379

Pour plus de détails couvrant les nuances des espaces blancs

Démontrez où la compression seule échoue lorsque des caractères mixtes successifs appartenant à la classe de caractères [: blank:] sont impliqués:

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

Remarque: Mes deux champs de chaîne au format printf sont séparés par 1 espace, 1 tabulation, 1 espace. Après la compression, cette séquence existe toujours. Dans la sortie du vidage octal, cela est représenté par la séquence ascii 040 011 040.

10
user3183018

Qui a besoin d'un programme (autre que le Shell)?

while read a b
do
    echo "$a $b"
done < f1.txt

Si vous souhaitez aligner les valeurs de la deuxième colonne, comme dans la réponse column de polym, utilisez printf au lieu de echo:

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt
6
Scott

C'est une vieille question qui a été résolue plusieurs fois. Juste pour être complet: j'ai eu un problème similaire, mais je voulais passer des lignes via un tuyau à un autre programme. J'ai utilisé xargs.

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

donc cat f1.txt | xargs -L1 semble produire exactement ce que vous voulez.

2
Martin Seitl