sed ведет себя по-разному в FreeBSD и в Linux?

12

Я использую как Linux, так и FreeBSD (в частности, я использую Debian Linux и PC-BSD), и я обнаружил кое-что странное sed.

Мне часто нужно конвертировать файлы с разделителями табуляции в значения, разделенные запятыми. Самый простой способ, который я знаю, это использовать sed, например так:

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

Это прекрасно работает в Linux: он заменяет каждую вкладку запятой ... но во FreeBSD это ничего не заменяет !!!

Я что-то пропустил? Есть ли синтаксис в FreeBSD sed, отличный от синтаксиса в Linux?

Barranka
источник

Ответы:

9

Возможно, вам следует использовать эту -Eопцию (или -rкак описано в руководстве ), чтобы сохранить совместимость с GNU Sed. В вашем случае вы можете установить Gnu Sed, если вы к нему привыкли (порт gsed на FreeBSD), или потребуется много усилий для переноса скриптов.

И запомни. Если какая-то команда в BSD не действует как версия этой утилиты gnu, это не значит, что она не работает;)


источник
1
Спасибо. -EОпция делает трюк (как на FreeBSD и Mac OS X).
Барранка
На моем FreeBSD 9 опция -E не помогает.
Арк-кун
6

Да, есть различные различия, поведение-i единственного, которого я знаю, вне головы.

Я никогда не использовал BSD, поэтому я не могу помочь с деталями, но trвместо этого можно использовать обходной путь :

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

Приятным побочным эффектом является то, что trдолжно быть значительно быстрее. Я проверил это на моем Linux, используя тестовый файл с 50000 строками, каждая из которых имела 2 вкладки:

$ 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
Тердон
источник
tr '\t' ,является более портативным, чем tr $'\t' ,. tr '[\t]' '[,]'будет даже переносимым на некоторые старые системы SysV.
Стефан Шазелас
вкладка является разделителем по умолчанию для cut. POSIX спецификации для trэто есть . Я был неправ насчет [необходимости для старого SysV. Как указывает эта спецификация POSIX, [она нужна только для диапазонов.
Стефан Шазелас
@StephaneChazelas, да, извините, не знаю, с чем я тогда это путаю. Спасибо за разъяснения в любом случае.
Terdon
4

Да, в отличие от GNU sedFreeBSD sedне интерпретирует escape-последовательности ANSI C, такие как \tрегулярные выражения.

Один из способов получить наименее распространенный знаменатель в этом случае - использовать printf.

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

Поведение sed -iдля редактирования файлов на месте можно сделать совместимым, если сразу за ним следует переключатель или опция -i, например, sed -i -e 's/x/X/g' fileработает как для GNU, sedтак и для FreeBSD sed.

Последние версии FreeBSD sed(FreeBSD 8.1 или новее) имеют -rпереключатель для повышения совместимости с GNU sed.

(Кроме того, использование классов символов POSIX в sedрегулярных выражениях также является хорошим способом обеспечения совместимости).

В качестве альтернативы POSIX-совместимой sedреализации см .: минимизированный - меньшая, более дешевая и быстрая реализация SED .

Крой
источник
3

Вы должны использовать буквенный TABсимвол вместо \t:

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

Смотрите этот комментарий Стефана по другому вопросу.

Следующая статья также может вас заинтересовать:

Я цитирую соответствующую часть:

Различия в

регулярных выражениях Синтаксис регулярных выражений слегка различается в разных версиях SED. Большинство различий связаны со специальными шаблонами escape, используемыми для сопоставления с непечатными символами, такими как ASCI-звонок и каналы.

Джозеф Р.
источник
0

После входа в систему я вижу следующее объявление и сохраняю его. Надеюсь, это будет полезно и для других

Хотите использовать sed (1) для редактирования файла на месте? Ну, чтобы заменить каждое 'e' на 'o' в файле с именем 'foo', вы можете сделать:

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

И вы получите резервную копию оригинала в файле с именем 'foo.bak', но если вы не хотите делать резервную копию:

sed -i '' s/e/o/g foo
TradeNarK
источник
-iвариант был покрыт уже , хотя
Джефф Schaller