sed se comporte différemment sous FreeBSD et Linux?

12

J'utilise à la fois Linux et FreeBSD (en particulier, j'utilise Debian Linux et PC-BSD), et j'ai trouvé quelque chose de bizarre sed.

J'ai souvent besoin de convertir des fichiers de "valeurs séparées par des tabulations" en "valeurs séparées par des virgules". La façon la plus simple que je connaisse est d'utiliser sed, comme ceci:

sed 's/\t/,/g' inputFile.txt > outputFile.csv

Cela fonctionne parfaitement sous Linux: il remplace chaque onglet par une virgule ... mais sur FreeBSD, il ne remplace rien !!!

Suis-je en train de manquer quelque chose? Existe-t-il une syntaxe avec FreeBSD seddifférente de celle sous Linux?

Barranka
la source

Réponses:

9

Vous devriez peut-être utiliser l' -Eoption (ou -rcomme expliqué dans le manuel ) pour conserver la compatibilité avec GNU Sed. Dans votre cas, vous pouvez installer Gnu Sed si vous y êtes habitué (port gsed sur FreeBSD), ou il faudra un long effort pour porter des scripts.

Et rappelez-vous. Si une commande sur BSD n'agit pas comme la version gnu de cet utilitaire, cela ne signifie pas qu'elle est cassée;)


la source
1
Je vous remercie. L' -Eoption fait l'affaire (à la fois sur FreeBSD et sur Mac OS X).
Barranka
Sur mon FreeBSD 9, l'option -E n'aide pas.
Ark-kun
6

Oui, il y a différentes différences, le comportement d'-i être le seul que je connaisse du haut de ma tête.

Je n'ai jamais utilisé BSD, je ne peux donc pas vraiment aider avec les détails, mais une solution de contournement pourrait être d'utiliser à la trplace:

tr '\t' , < inputFile.txt > outputFile.csv

Un effet secondaire agréable est que cela trdevrait être beaucoup plus rapide. J'ai testé cela sur mon Linux en utilisant un fichier de test avec 50000 lignes, chacune ayant 2 onglets:

$ time tr '\t' , < foo.txt > /dev/null 

real    0m0.004s
user    0m0.000s
sys     0m0.000s

$ time sed 's/\t/,/g' foo.txt > /dev/null 

real    0m0.039s
user    0m0.036s
sys     0m0.000s
terdon
la source
tr '\t' ,est plus portable que tr $'\t' ,. tr '[\t]' '[,]'serait même portable sur certains anciens systèmes SysV.
Stéphane Chazelas
tab est le délimiteur par défaut pour cut. La spécification POSIX pour trest . J'avais tort sur le [besoin de l'ancien SysV. Comme le souligne cette spécification POSIX, elle [n'est nécessaire que pour les plages.
Stéphane Chazelas
@StephaneChazelas il en est ainsi, désolé de ne pas savoir avec quoi je le confond alors. Merci pour la clarification dans tous les cas.
terdon
4

Oui, contrairement à GNU sedFreeBSD sedn'interprète pas les séquences d'échappement ANSI C comme \tdans les expressions régulières.

Dans ce cas, une façon d'obtenir un dénomiateur le moins courant est d'utiliser printf.

tab="$(printf '\t')"
printf '\t\n' | sed 's/'"${tab}"'/,/g'
printf '\t\n' | sed 's/'"$(printf '\t')"'/,/g'

Le comportement des sed -imodifications de fichiers sur place peut être rendu compatible si un commutateur ou une option suit immédiatement le -icommutateur, par exemple sed -i -e 's/x/X/g' filefonctionne à la fois pour GNU sedet FreeBSD sed.

Les versions récentes de FreeBSD sed(FreeBSD 8.1 ou plus récent) ont le -rcommutateur pour augmenter la compatibilité avec GNU sed.

(De plus, l'utilisation des classes de caractères POSIX dans sedles expressions régulières est également un bon moyen de garantir la compatibilité).

Pour une autre sedimplémentation conforme à POSIX, voir: minised - une implémentation SED plus petite, moins chère et plus rapide .

kroy
la source
3

Vous devez utiliser un TABcaractère littéral au lieu de \t:

sed 's/    /,/g' inputFile.txt > outputFile.csv

Voir ce commentaire de Stéphane sur une autre question.

L'article suivant peut également vous intéresser:

Je cite la partie pertinente:

Différences d'

expression régulière La syntaxe des expressions régulières diffère subtilement entre les différentes versions de SED. La plupart des différences impliquent des modèles d'échappement spéciaux utilisés pour faire correspondre les caractères non imprimables, tels que la cloche ASCI et les flux de formulaires.

Joseph R.
la source
0

Après la connexion, je vois l'annonce suivante et l'enregistre. J'espère que cela sera utile pour les autres aussi

Vous souhaitez utiliser sed (1) pour modifier un fichier en place? Eh bien, pour remplacer chaque «e» par un «o», dans un fichier nommé «foo», vous pouvez faire:

sed -i.bak s/e/o/g foo

Et vous obtiendrez une sauvegarde de l'original dans un fichier nommé 'foo.bak', mais si vous ne voulez pas de sauvegarde:

sed -i '' s/e/o/g foo
TradeNarK
la source
l' -ioption était déjà couvert , mais
Jeff Schaller