Why is sed not recognizing \t as a tab?

前端 未结 11 1575
伪装坚强ぢ
伪装坚强ぢ 2020-11-29 19:54
sed \"s/\\(.*\\)/\\t\\1/\" $filename > $sedTmpFile && mv $sedTmpFile $filename

I am expecting this sed script to insert a <

11条回答
  •  北海茫月
    2020-11-29 20:40

    @sedit was on the right path, but it's a bit awkward to define a variable.

    Solution (bash specific)

    The way to do this in bash is to put a dollar sign in front of your single quoted string.

    $ 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
    

    If your string needs to include variable expansion, you can put quoted strings together like so:

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

    Explanation

    In bash $'string' causes "ANSI-C expansion". And that is what most of us expect when we use things like \t, \r, \n, etc. From: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

    Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded...

    The expanded result is single-quoted, as if the dollar sign had not been present.

    Solution (if you must avoid bash)

    I personally think most efforts to avoid bash are silly because avoiding bashisms does NOT* make your code portable. (Your code will be less brittle if you shebang it to bash -eu than if you try to avoid bash and use sh [unless you are an absolute POSIX ninja].) But rather than have a religious argument about that, I'll just give you the BEST* answer.

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

    * BEST answer? Yes, because one example of what most anti-bash shell scripters would do wrong in their code is use echo '\t' as in @robrecord's answer. That will work for GNU echo, but not BSD echo. That is explained by The Open Group at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 And this is an example of why trying to avoid bashisms usually fail.

提交回复
热议问题