sed перетворити 4 пробіли в 2


14

Як можна перетворити 4 пробіли на 2 проміжки sed? Це можливо?

Я знайшов це, але він перетворює вкладку в пробіли:

sed -r ':f; s|^(\t*)\s{4}|\1\t|g; t f' file

Відповіді:


13

Опублікований сценарій перетворює 4 * n пробілів у n вкладок, лише якщо цим пробілам передують лише вкладки.

Якщо ви хочете замінити 4 пробіли на 2 пробіли, але лише з відступом, хоча це можна зробити за допомогою sed, я рекомендую натомість Perl.

perl -pe 's{^((?: {4})*)}{" " x (2*length($1)/4)}e' file

У sed:

sed -e 's/^/~/' -e ': r' -e 's/^\( *\)~    /\1  ~/' -e 't r' -e 's/~//' file

Ви можете використовувати indentзамість цього.


Я отримавNested quantifiers in regex; marked by <-- HERE in m/^( {4}* <-- HERE )/ at -e line 1.
eddygeek

1
@eddygeek О, справді, це та кілька інших помилок. Я замінив gobbledygook фактичним кодом perl.
Жил "ТАК - перестань бути злим"

5

Чи не працює прямо:

sed -r 's/ {4}/  /g'

Якщо ні, опублікуйте деякі дані, де це не вдалося.


1
Це не обмежується початком рядка. Якщо прикріпити його там, він не працюватиме для кількох матчів. Тож ми знаходимось на unix.stackexchange.com/a/375200/259620 нижче.
geek-merlin

Це не спрацює, якщо у вас комбінація двох пробілів та 4 пробілів, тому що два відступи з двох будуть рахуватися як чотири ...
Метт Флетчер

@aexl: Це не було вимогою ОП
Тор

@mattfletcher: питання стосувалося заміни 4 пробілів на 2, тому я не бачу вашої точки зору
Тор

4

Якщо потрібно конвертувати лише провідні пробіли:

sed 'h;s/[^ ].*//;s/    /  /g;G;s/\n *//'

З коментарями:

sed '
  h; # save a copy of the pattern space (filled with the current line)
     # onto the hold space
  s/[^ ].*//; # remove everything starting with the first non-space
              # from the pattern space. That leaves the leading space
              # characters
  s/    /  /g; # substitute every sequence of 4 spaces with 2.
  G; # append a newline and the hold space (the saved original line) to
     # the pattern space.
  s/\n *//; # remove that newline and the indentation of the original
            # line that follows it'

Також подивіться 'ts'налаштування та :retabкоманду vim


Використовуючи рішення vim, чи існує спосіб групового редагування кількох таких файлів за допомогою vim? Інакше я здогадуюсь, мені доведеться створити макрос?
chrisjlee

Зверніть увагу , що 'ts'і :retabне вирішення питання, але пов'язані між собою і може допомогти в рішенні вашої спільної мети. Можна зробити vim -- *.c, :set ts=...а потім :argdo retabабо :argdo retab!. Дивіться також 'sw'опцію та власні можливості відступу vim.
Стефан Шазелас

2
sed 's/^\( \+\)\1\1\1/\1\1/' file

Він працює, розділивши провідні пробіли на чотири екземпляри однієї групи (тому всі вони рівні), а потім замінивши їх лише двома екземплярами групи.


Як це покращує існуючі рішення?
Філіпос

1
Він зберігає непарні пробіли, впливає лише на провідний пробіл, не вимагає глобального прапора, його можна легко налаштувати для обробки будь-якої кількості пробілів (або вкладок) з обох сторін заміни і не використовує складніших команд sed, які може бути зручним для більш випадкових користувачів. Як і у багатьох справах, будь-яке вдосконалення є досить суб'єктивним, але якщо говорити самому: знайти це в сценарії було б значно простіше швидко поправити, ніж деякі інші перелічені рішення.
Мал

Цікаво. Радий, що я просив. Зазвичай зворотній зв'язок вважається злом, а не загальносвітовим прапором. Але ви могли б легко досягти того самого, використовуючи більш портативний сценарій (уникаючи \+). Дякую.
Філіпос

1
sed 's/    \{2,4\}\( \{0,1\}[^ ].*\)*/  \1/g' <input

Це повинно лише видавити провідні послідовності пробілів.

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