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


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 все время.


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

1

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

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

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

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

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


0

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

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


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

0

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


Так как он не работал с 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, не требует понимания этих флагов, но многие из них по соображениям совместимости.


-1

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

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


Почему именно три обратные косые черты?
— Майкл Гомер

3
Если я использую GNU sed, одного \ достаточно, так как никакого побега не требуется. Проблема в том, что BSD sedне поддерживает этот синтаксис для вкладок.
— иконоборчество

Не работает на моем El Capitan.
— Франклин Ю

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.