DISCLAIMER. English language used here only for compatibility (ASCII only), so any suggestions about my bad grammar (and not only it) will be greatly appreciated.

вторник, 22 ноября 2011 г.

xargs, arguments separator and escapes.

xargs uses blanks (not only newlines!) to split input line into arguments.
Though, there is some options, which turns this defailt off implicitly or
explicitly.

Here is summary:

    +--------+--------------------+---------------------+
    | Option | Argument separator | Escapes             |
    +--------+--------------------+---------------------+
    | -L     | blank              | Interpreted (work)  |
    +--------+--------------------+---------------------+
    | -d     | user defined       | Literal (not work)  | 
    +--------+--------------------+---------------------+
    | -I     | newline            | Interpreted (work)  |
    +--------+--------------------+---------------------+


Blank is space, tab or newline:

    # Examples {{{
    $ printf "a b\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    3
    a,b,c
    $ printf "a\tb\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    3
    a,b,c
    $ printf "a\nb\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    3
    a,b,c
    # }}}

Escape is backslash, double quote and single quote.

    # Exmaples {{{
    $ printf "a\ b\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    2
    a b,c
    $ printf "a' 'b\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    2
    a b,c
    $ printf "a\" \"b\nc" | xargs bash -c 'echo "$#"; IFS=','; echo "$*"' bash
    2
    a b,c
    # }}}



Now with more details.

'-L'

    Does _not_ change argument delimiter, backslash and quotes are _still_
    considered special (escape characters for argument delimiters).  It only
    limits number of input lines processed per command, but arguments in these
    lines are still separated by blanks (not newlines) and escapes still work.
    In other words, one input line _may_ contain more than one argument.

    # Examples {{{
    # (1st line split by blank (space) into two arguments)
        $ printf "a b\nc" | xargs -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a,b
        1
        c
    # backslash escape (interpreted, escape blank and 1st line does not split)
        $ printf "a\ b\nc" | xargs -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b
        1
        c
    # double quote escape (interpreted, escape blank and 1st line does not split)
        $ printf "\"a b\"\nc" | xargs -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b
        1
        c
    # single quote escape (interpreted, escape blank and 1st line does not split)
        $ printf "a' 'b\nc" | xargs  -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b
        1
        c
    # }}}

'-d'

    Change _argument_ delimiter to specified character, and quotes and
    backslash are no longer considered special. I.e. all characters are taken
    literally.

    Examples {{{
    # (newline, but not blank, now split arguments)
        $ printf "a b\nc" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a b,c
    # backslash (literal)
        $ printf "a\ b\nc" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a\ b,c
    # double quotes (literal)
        $ printf "a\" \"b\nc" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a" "b,c
    # single quotes (literal)
        $ printf "a' 'b\nc" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a' 'b,c
    # newline escape with backslash (interpreted? Strange..)
        $ printf "a b\\nc" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a b,c
    # newline escape with double quotes (literal, hence (?) does not escape)
        $ printf "a b\"\n\"c" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a b","c
    # newline escape with single quotes (literal, hence (?) does not escape)
        $ printf "a b'\n'c" | xargs -d'\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        2
        a b','c
    # with -L1 (does not split arguments by blank)
        $ printf "a b\nc" | xargs -d'\n' -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b
        1
        c
    # with -L1 and double quotes (literal)
        $ printf "a\" \"b\nc" | xargs -d'\n' -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a" "b
        1
        c
    # with -L1 newline escape with backslash (interpreted? Strange..)
        $ printf "a b\\nc" | xargs -d'\n' -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b
        1
        c
    # with -L1 newline escape with single quotes (literal, hence no error about unmatched quotes)
        $ printf "a b'\n'c" | xargs -d'\n' -L1 bash -c 'echo "$#"; IFS=','; echo "$*"' bash
        1
        a b'
        1
        'c
    # }}}

'-I'

    Change argument delimiter to _newline_, quotes and backslash are _still_
    considered special. Though, it seems, that newline can't be escaped,
    perhaps, because '-I' implies -'L1'.

    Examples {{{
    # (split arguments by newline, '-L1' in effect)
        $ printf "a b\nc" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a b
        1
        c
    # backslash escape (interpreted, but has no sense)
        sgf@shilvana:~$ printf "a\ b\nc" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a b
        1
        c
    # double quote escape (interpreted, but has no sense)
        sgf@shilvana:~$ printf "a\" \"b\nc" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a b
        1
        c
    # single quote escape (interpreted, but has no sense)
        $ printf "a' 'b\nc" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a b
        1
        c
    # newline escape with backslash (interpreted, but has no effect due to implied '-L1'?)
        $ printf "a b\\nc" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a b
        1
        c
    # newline escape with double quotes (interpreted, hence, cause "unmatched" error)
        sgf@shilvana:~$ printf "a \"b\n\"c" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
    # newline escape with single quotes (interpreted, hence, cause "unmatched" error)
        $ printf "a 'b\n'c" | xargs -I REPL bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
    # backslash with '-d' (literal)
        $ printf "a\ b\nc" | xargs -I REPL -d '\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a\ b
        1
        c
    # double quotes with '-d' (literal)
        $ printf "a\" \"b\nc" | xargs -I REPL -d '\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a" "b
        1
        c
    # single quotes with '-d' (literal)
        $ printf "a' 'b\nc" | xargs -I REPL -d '\n' bash -c 'echo "$#"; IFS=','; echo "$*"' bash REPL
        1
        a' 'b
        1
        c

    # }}}


Комментариев нет:

Отправить комментарий