Проста заміна вкладок таємничо не працює


44

Це повинно бути дійсно простим, але чомусь не працює:

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

Замість заміни символів вкладки він замінює tсимволи. Я намагався будь-який варіант цього питання, який я міг придумати, граючи з цитуванням і т. Д. Я гугл і знайшов усіх інших, використовуючи досить схожі вирази, і вони, здається, працюють на них.

Це -EОС X 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

якщо рубін також отримує неправильну відповідь, то це може бути ваша бібліотека regexp. (Я перевірив обидві ваші команди, і обидві замініть вкладку на 2 пробіли.) Тож, сподіваємось, якщо ви встановите Gnu sed, він також встановить правильну бібліотеку.
— ctrl-alt-delor

Відповіді:


64

Синтаксис \tсимволу вкладки в sed не є стандартним. Ця втеча є розширенням sed GNU . В Інтернеті ви знайдете безліч прикладів, які використовують його, оскільки багато людей використовують GNU sed (це реалізація sed у невбудованому Linux). Але OS X sed , як і інші * BSD sed, не підтримує \tвкладку і замість цього розглядає \tяк зміст зворотної косої риси, за якою слід t.

Є багато рішень, таких як:

  • Використовуйте буквальний символ вкладки.

    sed -i.bak 's/  /  /' file.txt
    
  • Використовуйте trабо printfдля створення символу вкладки.

    sed -i.bak "s/$(printf '\t')/  /" file.txt
    sed -i.bak "s/$(echo a | tr 'a' '\t')/  /" file.txt
    
  • Використовуйте синтаксис рядка bash, що дозволяє виконувати зворотні риси .

    sed -i.bak $'s/\t/  /' file.txt
    
  • Використовуйте Perl, Python або Ruby. Фрагмент Ruby, який ви опублікували, працює.


Для sed-скриптів, які містяться в ...sedскрипті (використовується через -fопцію), для мене є єдиною можливістю букви буквальних вкладок. Редагуючи це за допомогою vim, set noexpandtabважливо.
— Тобіас

Попередження. Використовуйте цю техніку "буквального символу вкладки" лише тоді, коли ви хочете, щоб ваш колега повернувся за вами і згодом зламав ваш сценарій. Використовуйте цю trтехніку лише в тому випадку, якщо ви хочете, щоб ваш колега зарізав вам обличчя, коли вони прочитали ваш сценарій.
— Бруно Броноський

Чи в другому блоці коду замінено другий знак подвійного лапки? Мені довелося перенести його туди, де зараз є заключна одноцінова пропозиція.
— Еллен Спертус

Дякую за посилання на синтаксис рядка bash ... Я поняття не мав (і це найкращий варіант, IMHO).
— levigroker

sed $'s/<regex>/\t/' file.txtпрацює для вставки, але, $здається, зламає мій сценарій, коли я намагаюся включити частину регулярного вираження в свою заміну, тобто sed $'s,\(ontology/[0-9]\+\),\t\txxx\1xxx\t\t,'дає `xxxxxx`, коли очікуване значення збігу замінено на ``. Чи існує еквівалент, \1коли використовується синтаксис рядка bash? Редагувати: мається на увазі символ Unicode U + 231C посередині xxx <U + 231C> xxx.
— Джош

14

Використовуйте специфічне котирування Bash, яке дозволяє використовувати рядки, як у C, так що справжній символ вкладки передається sed, а не послідовності втечі:

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

1
Також називається "ANSI-C" цитуванням, якщо інші хочуть дізнатися більше інформації про це.
— wisbucky

2
Здається, працює над будь-якою оболонкою Bourne, працює також і на UNHIX-і, що не мають башти. Однак не працює на csh-варіантах.
— jornane

2
sed -i $'s/\t/  /g' file.txt 

працює для мене на OS X і є тією ж командою, яку я використовую в Linux постійно.


Зауважте, що це замінює всі вкладки в кожному рядку, тоді як OP має намір замінити лише перший (судячи з команди, яку вони використовують).
— Kusalananda

1

Як зазначалося, не всі sedреалізації підтримують позначення \tяк горизонтальної вкладки.

Ви можете легко досягти своєї заміни за допомогою:

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

Це виконує заміну in situ, яка зберігає ваш вихідний файл як "* .old". Perl дозволяє чергувати роздільники для класичного, /роблячи вираз набагато зрозумілішим (тобто позбавленим синдрому "нахиленої зубочистки").

+Каже один або більше повторень символу табуляції повинні бути замінені. gМодифікатор дозволяє глобальну заміну на протязі кінці кожного рядка.


0

Ви також можете використовувати echoвсередині sed:

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


Зауважте, що це echo '\t'буде просто виведенням \tу реалізацію деяких оболонок echo.
— Kusalananda

0

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


Оскільки він не працював і з Ruby, я не впевнений, чому б я зробив висновок, що sedпроблема ОС X. Чи є у вас підстави вважати, що це проблема? Я був би радий встановити GNU sed, якби я мав підстави вважати, що це вирішить проблему, але, схоже, я це майже виключив.
— іконоборство

З Ruby вам доведеться використовувати лише одну зворотну косу ruby -pe '$_.gsub!(/\t/," ")' < file.txt
— рису

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 Це повинно зробити трюк.

Вам потрібно уникнути втечі (звідси 3 \ s), щоб sed зрозумів, що ви намагаєтесь використовувати символ \ t у регулярному виразі, коли все замінено ...


Чому конкретно три відхилення від накипу?
— Майкл Гомер

3
Якщо я використовую GNU sed, одного \ достатньо, тому що не потрібно уникати. Проблема полягає в тому, що BSD sedне підтримує цей синтаксис для вкладок.
— іконоборство

Не працює на моєму El Capitan.
— Франклін Ю

-4

Це працювало для мене.

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


3
Це тому, що ви використовуєте GNU sed. Це не те, що використовує ОП.
— Kusalananda
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.