Простая замена седана при загадочных ошибках

44

Это должно быть действительно просто, но по какой-то причине это не работает:

sed -i.bak -E 's/\t/  /' file.txt

Вместо замены символов табуляции, это замена tсимволов. Я перепробовал все варианты, которые мог придумать, играя с цитатами и т. Д. Я гуглил и нашел всех остальных, использующих довольно похожие выражения, и они, похоже, работают на них.

Это -EOS X вещь. Я думал, что сбой может быть результатом какой-то странной причуды OS X sed, поэтому я попробовал это и с Ruby (без -i), и получил тот же результат:

ruby -pe '$_.gsub!(/\t/,"  ")' < file.txt > file.new

Я использую Bash 3.2.51 на OS X и iTerm, хотя я не понимаю, насколько это может быть очень актуально. Я не установил никаких странных переменных окружения, хотя могу опубликовать любые, которые, по вашему мнению, могут иметь отношение к делу.

Что может быть не так?

UPDATE : Должно бытья сделал некоторую другую ошибку или опечаткукогда я попробовал версию Ruby, такЖиль указывает, что он делает работу (и я никогда и не было ему рулить меня неправильно!). Я не уверен, что случилось, но я почти уверен, что это была моя ошибка.

иконоборец
источник
5
Может быть, вы должны попытаться заменить \tв sedзаявлении, CTRL-V<TAB>где <TAB>находится клавиша табуляции и клавиша CTRL-Vуправления и vнажата вместе.
unxnut
если ruby ​​также получает неправильный ответ, то это может быть ваша библиотека регулярных выражений. (Я протестировал обе ваши команды, и обе заменили табуляцию двумя пробелами.) Поэтому, надеюсь, если вы установите Gnu sed, он также установит правильную библиотеку.
Ctrl-Alt-Delor

Ответы:

64

Синтаксис \tсимвола табуляции в sed не является стандартным. Этот побег является расширением GNU sed . В Интернете вы найдете множество примеров, которые используют его, потому что многие люди используют GNU sed (это реализация sed на не встроенных Linux). Но OS X sed , как и другие * BSD sed, не поддерживает \ttab и вместо этого обрабатывает \tкак означающий обратную косую черту, за которой следует t.

Есть много решений, таких как:

Жиль "ТАК - перестань быть злым"
источник
Для сценариев sed, которые содержатся в ...sedсценарии (используется через -foption), буквенные символы табуляции кажутся мне единственной возможностью. При редактировании этого с vim, set noexpandtabэто важно.
Тобиас
Предупреждение. Используйте эту технику «буквального символа табуляции» только в том случае, если вы хотите, чтобы ваш коллега вернулся за вами и позже нарушил ваш сценарий. Используйте эту trтехнику только в том случае, если вы хотите, чтобы ваш коллега ударил вас в лицо, когда они читают ваш сценарий.
Бруно Броноски
Вторая двойная кавычка не помещена во второй блок кода? Мне пришлось переместить его туда, где сейчас находится заключительная одинарная кавычка.
Эллен Спертус
Спасибо за ссылку на синтаксис строки bash ... Я понятия не имел (и это лучший вариант, ИМХО).
левигрокер
sed $'s/<regex>/\t/' file.txtработает для вставки, но, $кажется, нарушает мой скрипт, когда я пытаюсь включить часть регулярного выражения в мою замену, то есть sed $'s,\(ontology/[0-9]\+\),\t\txxx\1xxx\t\t,'дает `xxxxxx` с моим ожидаемым значением соответствия, замененным на` `. Есть ли эквивалент \1при использовании строкового синтаксиса bash? Редактировать: предполагается, что символ Юникода U + 231C находится в середине xxx <U + 231C> xxx.
Джош
14

Используйте специфичные для Bash кавычки, которые позволяют вам использовать строки, как в C, так чтобы реальный символ табуляции передавался в sed, а не в escape-последовательности:

sed -i.bak -E $'s/\t/  /' file.txt
Кристиан Чиупиту
источник
1
Также называется «цитирование ANSI-C», если другие хотят найти больше информации об этом.
wisbucky
2
Кажется, работает на любой оболочке Bourne, работает и на не-bash UNIX. Не работает с csh-вариантами.
Йорн
3
sed -i $'s/\t/  /g' file.txt 

работает для меня на OS X и это та же команда, которую я использую на Linux все время.

user193377
источник
Обратите внимание, что это заменяет все вкладки в каждой строке, тогда как OP намеревается заменить только первую (судя по команде, которую они используют).
Кусалананда
1

Как уже отмечалось, не все sedреализации поддерживают обозначение \tв виде горизонтальной табуляции.

Вы можете легко добиться замены с помощью:

 perl -pi.old -e 's{\t+}{ }g' file.txt

Это выполняет замену на месте, которая сохраняет ваш исходный файл как «* .old». Perl позволяет использовать альтернативные разделители для классики, /делая выражение намного более читабельным (т.е. лишенным синдрома «наклоняющейся зубочистки»).

+Говорит один или более повторений символа табуляции должны быть заменены. gМодификатор позволяет глобальную замену на протяжении конце каждой строки.

JRFerguson
источник
0

Вы также можете использовать echoвнутри sed:

sed -i "s/$(echo '\t')//g"

saulR
источник
Обратите внимание, echo '\t'что \tв некоторых оболочках будет просто вывод echo.
Кусалананда
0

Если вы хотите более мощный sed(поддерживающий \tи больше), чем тот, что в OS X, установите GNU sed .

vinc17
источник
Так как он не работал с Ruby, я не уверен, почему я решил, что sedпроблема в OS X. У вас есть основания полагать, что это проблема? Я был бы счастлив установить GNU sed, если бы у меня была причина полагать, что это решит проблему, но кажется, что я в значительной степени исключил это.
иконоборчество
С Ruby вам придется использовать только одну обратную косую черту:ruby -pe '$_.gsub!(/\t/," ")' < file.txt
vinc17
0

Если это нормально, требовать bashили zshв качестве оболочки, то это самое простое решение, которое я могу придумать:

sed "s/$(echo -n -e "\t")/ /" file.txt

Однако обратите внимание, что echoфлаги ( -nи -e) не определены в POSIX, поэтому оболочка, соответствующая POSIX, не требует понимания этих флагов, но многие из них по соображениям совместимости.

Mecki
источник
-1

Я удивлен, что никто не предложил очень простое решение: sed -i.bak -E 's/\\\t/ /' file.txt это должно сработать.

Вам нужно экранировать escape (отсюда 3 \ s), чтобы sed мог понять, что вы пытаетесь использовать символ \ t в регулярном выражении, когда все подставляется ...

Vas
источник
Почему именно три обратные косые черты?
Майкл Гомер
3
Если я использую GNU sed, одного \ достаточно, так как никакого побега не требуется. Проблема в том, что BSD sedне поддерживает этот синтаксис для вкладок.
иконоборчество
Не работает на моем El Capitan.
Франклин Ю
-4

Это сработало для меня.

sed -e 's / [\ t] / / g'

RChristensen
источник
3
Это потому, что вы используете GNU sed. Это не то, что использует OP.
Кусалананда