Поскольку sed может различаться между платформами (в частности, BSD / MacOSX и Linux), может быть полезно указать платформу, на которой вы используете sed.
О да; для уточнения: не все версии sed понимают \tзаменяющую часть выражения (она \tпрекрасно распознается в части сопоставления с образцом)
Джон Велдон,
3
Ой, хорошо, это довольно интересно. И странно. Почему вы заставляете его распознавать его в одном месте, а в другом - нет ...?
sixtyfootersdude
2
Вызывается из скрипта, это не сработает: вкладки будут игнорироваться sh. Например, следующий код из сценария оболочки добавит $ TEXT_TO_ADD без добавления табуляции перед ним: sed "$ {LINE} a \\ $ TEXT_TO_ADD" $ FILE.
Вы были на правильном пути, $'string'но без объяснения причин. На самом деле я подозреваю, что из-за чрезвычайно неудобного использования вы, вероятно, не полностью понимаете это (как большинство из нас делает с bash). См. Мое объяснение ниже: stackoverflow.com/a/43190120/117471
Бруно Броноски
1
Помните, что BASH не расширяет переменные, как $TABвнутри одинарных кавычек, поэтому вам нужно использовать двойные кавычки.
nealmcb 07
Будьте осторожны при использовании *внутри двойных кавычек ... это будет рассматриваться как глобус, а не как регулярное выражение, которое вы намереваетесь.
levigroker
28
@sedit был на правильном пути, но определять переменную немного неудобно.
Решение (специфично для bash)
В bash это можно сделать, поставив знак доллара перед строкой в одиночных кавычках.
$ echo -e '1\n2\n3'123
$ echo -e '1\n2\n3'| sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3'| sed $'s/.*/\t&/g'123
Если ваша строка должна включать расширение переменных, вы можете объединить строки в кавычки следующим образом:
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3'| sed "s/.*/$timestamp"$'\t&/g'149123795811491237958214912379583
Особо обрабатываются слова вида $ 'строка' . Слово расширяется до строки заменяется с заменой экранированных символов обратной косой черты, как указано в стандарте ANSI C. Управляющие последовательности с обратной косой чертой, если они есть, декодируются ...
Расширенный результат заключен в одинарные кавычки, как если бы знака доллара не было.
Решение (если вы должны избегать bash)
Я лично считаю, что большинство попыток избежать bash глупо, потому что избегание bashisms НЕ * делает ваш код переносимым. (Ваш код будет менее хрупким, если вы его измените, bash -euчем если вы попытаетесь избежать bash и использовать sh[если вы не являетесь абсолютным ниндзя POSIX].) Но вместо того, чтобы иметь религиозные аргументы по этому поводу, я просто дам вам НАИЛУЧШЕЕ * ответ.
$ echo -e '1\n2\n3'| sed "s/.*/$(printf '\t')&/g"123
* Лучший ответ? Да, потому что один из примеров того, что большинство сценариев оболочки анти-bash сделали бы неправильно в своем коде, - это использование, echo '\t'как в ответе @ robrecord . Это будет работать для GNU echo, но не для BSD echo. Это объясняет The Open Group на http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16. И это пример того, почему попытки избежать башизмов обычно терпят неудачу.
Забавно, что вы используете особую функцию «GNU echo» (интерпретируете \ t как символ табуляции) для устранения специфической ошибки «BSD sed» (интерпретируя \ t как 2 отдельных символа). Предположительно, если у вас есть «GNU echo», у вас также будет «GNU sed». В этом случае вам не нужно использовать эхо. С BSD echo echo '\t'выводит 2 отдельных символа. Переносимый способ POSIX - использовать printf '\t'. Вот почему я говорю: не пытайтесь сделать свой код переносимым, не используя bash. Это сложнее, чем ты думаешь. Использование bash- это самая портативная вещь, которую может сделать большинство из нас.
Бруно Броноски
3
Вам не нужно использовать sed замену, когда на самом деле вы просто хотите вставить табуляцию перед строкой. Замена в этом случае - дорогостоящая операция по сравнению с простой распечаткой, особенно когда вы работаете с большими файлами. Его тоже легче читать, так как это не регулярное выражение.
sedне поддерживает \t, ни другие escape-последовательности, как \nв этом отношении. Единственный способ, который я нашел для этого, - это вставить символ табуляции в скрипт, используяsed .
Тем не менее, вы можете рассмотреть возможность использования Perl или Python. Вот небольшой сценарий Python, который я написал, который я использую для всех регулярных выражений потока:
Я думаю, что другие разъяснили это адекватно для других подходов ( sed, AWKи т. Д.). Тем не менее, следующие мои bashответы (проверенные на macOS High Sierra и CentOS 6/7).
1) Если OP хотел бы использовать метод поиска и замены, аналогичный тому, что они первоначально предлагали, я бы предложил использовать perlдля этого, как показано ниже. Примечания: обратная косая черта перед круглыми скобками для регулярного выражения не обязательна, и эта строка кода отражает, как $1лучше использовать, чем \1с perlоператором подстановки (например, согласно документации Perl 5 ).
2) Однако, как указано ghostdog74 , поскольку желаемая операция на самом деле состоит в том, чтобы просто добавить вкладку в начале каждой строки перед изменением файла tmp во входной / целевой файл ( $filename), я бы рекомендовал perlснова, но со следующей модификацией (s):
Ответы:
Не все версии
sed
понимают\t
. Вместо этого просто вставьте буквальную табуляцию (нажмите Ctrl- Vзатем Tab).источник
\t
заменяющую часть выражения (она\t
прекрасно распознается в части сопоставления с образцом)Используя Bash, вы можете программно вставить символ TAB следующим образом:
источник
$'string'
но без объяснения причин. На самом деле я подозреваю, что из-за чрезвычайно неудобного использования вы, вероятно, не полностью понимаете это (как большинство из нас делает с bash). См. Мое объяснение ниже: stackoverflow.com/a/43190120/117471$TAB
внутри одинарных кавычек, поэтому вам нужно использовать двойные кавычки.*
внутри двойных кавычек ... это будет рассматриваться как глобус, а не как регулярное выражение, которое вы намереваетесь.@sedit был на правильном пути, но определять переменную немного неудобно.
Решение (специфично для bash)
В bash это можно сделать, поставив знак доллара перед строкой в одиночных кавычках.
Если ваша строка должна включать расширение переменных, вы можете объединить строки в кавычки следующим образом:
Объяснение
В bash
$'string'
вызывает "расширение ANSI-C". И это то , что большинство из нас ожидает , когда мы используем такие вещи , как\t
,\r
,\n
и т.д. От: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-QuotingРешение (если вы должны избегать bash)
Я лично считаю, что большинство попыток избежать bash глупо, потому что избегание bashisms НЕ * делает ваш код переносимым. (Ваш код будет менее хрупким, если вы его измените,
bash -eu
чем если вы попытаетесь избежать bash и использоватьsh
[если вы не являетесь абсолютным ниндзя POSIX].) Но вместо того, чтобы иметь религиозные аргументы по этому поводу, я просто дам вам НАИЛУЧШЕЕ * ответ.* Лучший ответ? Да, потому что один из примеров того, что большинство сценариев оболочки анти-bash сделали бы неправильно в своем коде, - это использование,
echo '\t'
как в ответе @ robrecord . Это будет работать для GNU echo, но не для BSD echo. Это объясняет The Open Group на http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16. И это пример того, почему попытки избежать башизмов обычно терпят неудачу.источник
Я использовал что-то подобное с оболочкой Bash в Ubuntu 12.04 (LTS):
Чтобы добавить новую строку с табуляцией, вторая при совпадении первой :
Чтобы заменить первое на вкладку, второе :
источник
\\t
а не использование\t
.Используйте
$(echo '\t')
. Вам понадобятся цитаты вокруг выкройки.Например. Чтобы удалить вкладку:
источник
echo '\t'
выводит 2 отдельных символа. Переносимый способ POSIX - использоватьprintf '\t'
. Вот почему я говорю: не пытайтесь сделать свой код переносимым, не используя bash. Это сложнее, чем ты думаешь. Использованиеbash
- это самая портативная вещь, которую может сделать большинство из нас.Вам не нужно использовать
sed
замену, когда на самом деле вы просто хотите вставить табуляцию перед строкой. Замена в этом случае - дорогостоящая операция по сравнению с простой распечаткой, особенно когда вы работаете с большими файлами. Его тоже легче читать, так как это не регулярное выражение.например, используя awk
источник
Я использовал это на Mac:
Использовал эту ссылку для справки
источник
sed
не поддерживает\t
, ни другие escape-последовательности, как\n
в этом отношении. Единственный способ, который я нашел для этого, - это вставить символ табуляции в скрипт, используяsed
.Тем не менее, вы можете рассмотреть возможность использования Perl или Python. Вот небольшой сценарий Python, который я написал, который я использую для всех регулярных выражений потока:
источник
Вместо BSD sed я использую perl:
источник
Я думаю, что другие разъяснили это адекватно для других подходов (
sed
,AWK
и т. Д.). Тем не менее, следующие моиbash
ответы (проверенные на macOS High Sierra и CentOS 6/7).1) Если OP хотел бы использовать метод поиска и замены, аналогичный тому, что они первоначально предлагали, я бы предложил использовать
perl
для этого, как показано ниже. Примечания: обратная косая черта перед круглыми скобками для регулярного выражения не обязательна, и эта строка кода отражает, как$1
лучше использовать, чем\1
сperl
оператором подстановки (например, согласно документации Perl 5 ).2) Однако, как указано ghostdog74 , поскольку желаемая операция на самом деле состоит в том, чтобы просто добавить вкладку в начале каждой строки перед изменением файла tmp во входной / целевой файл (
$filename
), я бы рекомендовалperl
снова, но со следующей модификацией (s):3) Конечно, файл tmp излишний , поэтому лучше просто сделать все «на месте» (добавить
-i
флаг) и упростить задачу до более элегантного однострочника систочник