J'ai un fichier créé en copiant le contenu d'un document DOCX avec LibreOffice dans un fichier texte. J'ai modifié le fichier avec sed
pour supprimer des espaces supplémentaires et d'autres éléments, mais j'ai remarqué un espace insensible aux commandes habituelles:
sed -r 's:some-text :some-text:g' -i file
Après avoir utilisé cat -A file
, j'ai découvert que cela ressemblait à ceci:
<p>M-BM- Lorem ipsum</p>
Comment l'enlever?
Après avoir essayé beaucoup de choses, j'ai finalement trouvé une solution. Pour remplacer ce caractère étrange par sed, vous devez copier et coller le texte exact qui contient cet espace étrange à proximité, puis le coller directement dans la commande sed:
sed -r 's:paste-here:<p>:g' -i file
Ce qui ressemblera à ceci dans la commande sed:
sed -r 's:<p> :<p>:g' -i file
mais cela fonctionnera quand même.
Les caractères M-BM-
sont une représentation ASCII de la séquence d'octets 0xc2 0xa0
, qui est le codage UTF8 du caractère unicode A0
- un espace insécable. Ce caractère peut être inséré dans les documents LibreOffice et Microsoft Word en utilisant la séquence de touches Ctrl+Shift+SPACE.
Par exemple, si nous créons un nouveau document .odt dans LibreOffice et tapons ABCCtrl+Shift+SPACEDEF, puis Save As... Text
(sans tenir compte du fait que le document peut contenir des fonctions qui ne peuvent pas être enregistrées dans ce format), puis affichez le fichier .txt obtenu avec cat
:
$ cat nbsp.txt
ABC DEF
et ensuite avec le commutateur -v
pour afficher les caractères non imprimables
$ cat -v nbsp.txt
M-oM-;M-?ABCM-BM- DEF
Notez que nous obtenons également une séquence initiale M-oM-;M-?
ou hexadécimale 0xef 0xbb 0xbf
qui correspond à UTF8 marque d'ordre des octets (BOM) cohérente avec le type de fichier indiqué par file
commande c'est à dire.
$ file nbsp.txt
nbsp.txt: UTF-8 Unicode (with BOM) text
Utiliser od
pour imprimer les valeurs hexadécimales dans l'ordre des octets que nous voyons
$ od -tx1 nbsp.txt
0000000 ef bb bf 41 42 43 c2 a0 44 45 46 0a
0000014
Il est possible de manipuler ces caractères à l'aide d'outils standard tels que sed
ou tr
en spécifiant les codes hexadécimaux sous forme de séquences d'échappement, par ex. remplacer l'espace insécable par un espace ASCII
$ sed 's/\xc2\xa0/ /g' nbsp.txt
ABC DEF
Vérifier à nouveau avec od
confirme le remplacement par un ASCII espace 0x20 (décimal 32) ordinaire.
$ sed 's/\xc2\xa0/ /g' nbsp.txt | od -tx1
0000000 ef bb bf 41 42 43 20 44 45 46 0a
0000013
Dans gnome-terminal (et peut-être avec d'autres émulateurs de terminal compatibles UTF8), il est également possible de saisir la valeur du point de code unicode directement à l'aide de la séquence de touches. Ctrl+Shift+u suivi d'une valeur hexadécimale puis le Enter key - la séquence apparaît initialement sous la forme u..̲. mais le personnage doit composer lorsque vous appuyez sur Enter par exemple. pour le même remplacement d'espace insécable que nous pouvons faire
$ sed 's/Ctrl+Shift+ua0
qui affiche comme
$ sed 's/̲/̲u̲a̲0̲
puis complète comme
$ sed 's/ / /g' nbsp.txt
ABC DEF
En utilisant cat -v
nous pouvons confirmer que la séquence M-BM-
est devenue un espace ordinaire
$ sed 's/ / /g' nbsp.txt | cat -v
M-oM-;M-?ABC DEF
Vous voudrez peut-être examiner des convertisseurs de codage plus génériques tels que iconv et uconv ainsi que.
"cat -v file" montrera les caractères non imprimables du fichier. Il suffit de rediriger la sortie vers un fichier temporaire et d’utiliser vim pour remplacer les caractères M-BM par rien.
% s/M-BM- // g
La solution la plus simple.
Vous pouvez supprimer ^ M des fichiers directement via la commande sed, par exemple:
sed -i'.bak' s/\r//g *.*
Si les modifications vous conviennent, supprimez les fichiers .bak:
rm -v *.bak
petit script pour supprimer ce caractère diable M-BM! ;) Juste au cas où aiderait n'importe qui.
#!/bin/bash
#############################################################################
# SCRIPT: M-BM-Remover.sh
# DESCRIPTION:
# This script will be able to detect hidden caracter "M-BM-",
# And/Or remove this !
# REVISIONS:
# 2014/06/11 YG
#____________________________________________________________________________
#
# PARAMETERS:
# > $1 :TARGET, (e.g. '"*.sh"' )
# > $2 :ACTION, (e.g. 'remove' )
# > $2 :BACKUP, (e.g. '' )
#
#############################################################################
TARGET=$1
ACTION=$2
BACKUP=$3
if [ "$TARGET" = "" ]
then
echo 'Need to choose target file'
echo 'M-BM-Remover [TARGET] [show/remove] [backup]'
echo 'Example : M-BM-Remover "*.sh" remove backup'
exit
fi
echo "ACTION = $ACTION";
echo "TARGET = $TARGET";
echo
if [ "$ACTION" = "show" ]
then
for file in $TARGET
do
if [ "$file" != "M-BM-Remover.sh" ]
then
echo "Traitement de $file ..."
cat -v $file | grep M-BM-
NB=`cat -v $file | grep M-BM- | wc -l`
echo "Occurence(s) : $NB"
fi
done
fi
if [ "$ACTION" = "remove" ] || [ "$ACTION" = "" ]
then
for file in $TARGET
do
if [ "$file" != "M-BM-Remover.sh" ]
then
echo "Traitement de $file ..."
NB=`cat -v $file | grep M-BM- | wc -l`
if [ "$BACKUP" = "backup" ]
then
cat $file > $file.bak
fi
cat -v $file.bak | sed s/M-BM-//g > $file
echo "Occurence(s) removed : $NB"
fi
echo
done
fi