Сед не признает \t вместо этого рассматривает это как 't' почему?

sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename

Я ожидаю, что этот sed script будет вставлять вкладку в шрифт каждой строки в $filename, но это не так. По какой-то причине он вместо этого вставляет t. Странно..

Ответ 1

Не все версии sed понимают \t. Просто вставьте вместо него буквальную вкладку (нажмите Ctrl - V, затем Tab).

Ответ 2

Используя Bash, вы можете вставить символ TAB программно так:

TAB=$'\t' 
echo 'line' | sed "s/.*/${TAB}&/g" 
echo 'line' | sed 's/.*/'"${TAB}"'&/g'   # use of Bash string concatenation

Ответ 3

Я использовал что-то вроде этого с оболочкой Bash на Ubuntu 12.04 (LTS):

Чтобы добавить новую строку с вкладкой, второй, когда первый соответствует:

sed -i '/first/a \\t second' filename

Чтобы заменить сначала вкладкой, второй:

sed -i 's/first/\\t second/g' filename

Ответ 4

Используйте $(echo '\t'). Вам понадобятся кавычки вокруг шаблона.

Eg. Чтобы удалить вкладку:

sed "s/$(echo '\t')//"

Ответ 5

@sedit был на правильном пути, но немного сложно определить переменную.

Решение (bash specific)

Способ сделать это в bash - это использовать знак доллара перед вашей одинарной кавычкой.

$ echo -e '1\n2\n3'
1
2
3

$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3

$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
    1
    2
    3

Если ваша строка должна включать расширение переменной, вы можете просто процитировать строки так:

$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958  1
1491237958  2
1491237958  3

Объяснение

В bash $'string' происходит "расширение ANSI-C". И это то, что большинство из нас ожидает, когда мы используем такие вещи, как \t, \r, \n и т.д. От: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

Слова формы $'string' обрабатываются специально. Слово расширяется для строки, с замененными символами с обратной косой чертой, как указано в стандарт ANSI C. Последующие последовательности обратной косой черты, если они есть, декодируется...

Расширенный результат одинарный, как если бы знак доллара не был присутствовали.

Решение (если вы должны избегать bash)

Я лично считаю, что большинство усилий по предотвращению bash глупы, потому что избегать багизмов НЕ делает ваш код переносимым. (Ваш код будет менее хрупким, если вы отмените его до bash -eu, чем если бы вы попытались избежать bash и использовать sh [если вы не являетесь абсолютным ниндзя POSIX].) Но вместо того, чтобы иметь религиозный аргумент об этом, Я просто дам вам ЛУЧШИЙ * ответ.

$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
    1
    2
    3

* Лучший ответ? Да, потому что один пример того, что большинство антивирусных скриптов bash ошибается в своем коде, использует echo '\t', как в @robrecord answer. Это будет работать для эха GNU, но не эхо BSD. Это объясняется The Open Group в http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16

Ответ 6

Вам не нужно использовать sed для подстановки, если на самом деле вы просто хотите вставить вкладку перед строкой. Замена для этого случая - дорогостоящая операция по сравнению с просто ее распечаткой, особенно когда вы работаете с большими файлами. Его легче читать также как не регулярное выражение.

например, используя awk

awk '{print "\t"$0}' $filename > temp && mv temp $filename

Ответ 7

sed не поддерживает \t, а также другие escape-последовательности, такие как \n. Единственный способ, которым я нашел это, - фактически вставить символ табуляции в script с помощью sed.

Тем не менее, вы можете рассмотреть возможность использования Perl или Python. Здесь короткий Python script я написал, что я использую для всех потоков regex'ing:

#!/usr/bin/env python
import sys
import re

def main(args):
  if len(args) < 2:
    print >> sys.stderr, 'Usage: <search-pattern> <replace-expr>'
    raise SystemExit

  p = re.compile(args[0], re.MULTILINE | re.DOTALL)
  s = sys.stdin.read()
  print p.sub(args[1], s),

if __name__ == '__main__':
  main(sys.argv[1:])

Ответ 9

Вместо BSD sed я использую perl:

[email protected]:~$ python -c "print('\t\t\thi')" |perl -0777pe "s/\t/ /g"
   hi