28156


sed
で、テキストファイルの一部分を他のテキストファイルでもって置換するスクリプトを記述していました。その際、改行だと問題なく動作するが、セミコロンを使うとエラーになる事象に遭遇しました。

これは、何が起きているのでしょうか。

スクリプト: コメントアウト部分の方を利用するとエラー(`sed: -e expression #1, char 0: unmatched`{'`)になる

[code]

    #!/bin/bash
    
    cat template.txt |
        #     sed '/TMPL/{r template-value.txt; d;}'
        sed '/TMPL/{
            r template-value.txt
            d
        }'
    
[/code]

参考までに、 template.txt:

[code]

    abc
    efg
    TMPL
    hij
    
[/code]

template-value.txt:

[code]

    zzzz
    zz
    zzzz
    
[/code]


CC BY-SA 3.0
2016-08-09T11:05:50.657
28155
2016-08-09T12:04:55.913
754
question
sed
sed で、セミコロンを使うとおかしくなる


GNU sed のソースコードを眺めてみると `r` コマンドの場合、改行(newline)か EOF
までをファイル名として取り込んでしまうので、同じ行に別のコマンドを指定できない様です。そのため `}`(close brace)
も別の行に置く必要があります。

※ `#if 0 /*XXX ZZZ 1998-09-12 kpp: added, then had second thoughts*/`
となっているので、当時の GNU sed ではエラーにならなかったのかもしれません

**sed-4.2.2/sed/compile.c**

[code]

    /* Read a program (or a subprogram within `{' `}' pairs) in and store
       the compiled form in `*vector'.  Return a pointer to the new vector.  */
    static struct vector *compile_program (struct vector *);
    static struct vector *
    compile_program(vector)
               :
    
      case 'r':
        b = read_filename();
        cur_cmd->x.fname = ck_strdup(get_buffer(b));
        free_buffer(b);
        break;
    
               :
    
    /* Read in a filename for a `r', `w', or `s///w' command. */
    static struct buffer *read_filename (void);
    static struct buffer *
    read_filename()
    {
      struct buffer *b;
      int ch;
    
      b = init_buffer();
      ch = in_nonblank();
      while (ch != EOF && ch != '\n')
        {
    #if 0 /*XXX ZZZ 1998-09-12 kpp: added, then had second thoughts*/
          if (posixicity == POSIXLY_EXTENDED)
            if (ch == ';' || ch == '#')
              {
                savchar(ch);
                break;
              }
    #endif
          ch = add_then_next(b, ch);
        }
      add1_buffer(b, '\0');
      return b;
    }
    
[/code]

なお、bash の場合は `$'string'` 記法があるので、以下の様にも書く事ができます。

[code]

    $ cat template.txt | sed $'/TMPL/{r template-value.txt\nd;}'
    
[/code]


CC BY-SA 3.0
2016-08-09T12:04:55.913
28156
2016-08-09T12:04:55.913
28155
answer