В vim это, кажется, можно сделать так:
:s/^\t\+/\=repeat(' ',len(submatch(0)))
Я не выяснил, как это переводится в sed. Я попробовал следующее:
sed -ri "s/^\t\+/\=repeat(' ',len(submatch(0)))/g" test.txt
Похоже, приказ не возымел никакого эффекта.
решение1
Это то, expand
для чего, например expand -t 4 file.txt
.
expand
не будет редактировать исходный файл, но вы можете перенаправить его на новый файл и mv
поверх исходного, или использовать, sponge
если он у вас установлен, например
expand -t 4 file.txt > file.new && mv file.new file.txt
or
expand -t 4 file.txt | sponge file.txt
К вашему сведению, смотрите, unexpand
как сделать наоборот, преобразовать несколько пробелов в табуляции.
Оба expand
поддерживают unexpand
использование вкладок фиксированной ширины (например , -t 4
или и т. д.)-t 8
илисписок позиций табуляции (например -t 4,12,32
, ). У них также есть опции для преобразования только начальных, ведущих пробелов/табуляции. Подробности см. на страницах man.
Для получения дополнительной информации sponge
см. man sponge
иСуществует ли стандартная альтернатива губке, позволяющая втягивать файл в себя?. Короче говоря, он делает перенаправление и mv для вас, используя временный файл. Кстати, никогда не пытайтесь перенаправить stdout в тот же файл, который в данный момент используется как stdin. Оболочка перезапишет его еще до того, как он будет прочитан.
sponge
это изmoreutilsупаковка.
P.S.: Смотрите такжеотступ GNUили один из многих других подобных инструментов переформатирования исходного кода.
решение2
$ cat -T /tmp/test.txt
^I^I^I3^I<= this final tab should remain
^I^I2
^I1
Используя sed:
sed ':loop;s/^\( *\)\t/\1 /;tloop' /tmp/test.txt | cat -T
3^I<= this final tab should remain
2
1
Вышеуказанный пример устанавливает цикл (по иронии судьбы обозначенный как loop
), который захватывает все начальные пробелы и начальную табуляцию; заменяет пробелы и преобразует табуляцию в 4 пробела; в случае успеха ( t
) он возвращается к циклу. Смотритеhttps://stackoverflow.com/a/35017207/493161