読者です 読者をやめる 読者になる 読者になる

HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

ansibleで改行コードの変換

ansilbleのplaybookの中でpatchモジュールを使って転送したファイルにpatchをあててたのがあったのですが、なぜかパッチファイルと適用対象ファイルの改行コードがLFの時は動作するのに、CRLFだと駄目という現象が起きたので、急遽playbookの中で改行コードを変換する方法を調べてみました。

使うモジュールはこちら
replace - Replace all instances of a particular string in a file using a back-referenced regular expression. — Ansible Documentation

テスト用にこんな内容のファイルを用意します。中身は一緒で改行コードがLFのものとCRLFのものです。

$ cat org_crlf.txt 
hoge
hoge
$ cat org_lf.txt 
hoge
hoge
$ file hoge_*
hoge_crlf_org.txt: ASCII text, with CRLF line terminators
hoge_lf_org.txt:   ASCII text

でもって、次のようなplaybookを作って実行します。

- hosts: 127.0.0.1
  connection: local
  strategy: debug
  tasks:
    - copy: 
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - {src: "org_crlf.txt", dest: "./hoge_crlf_to_lf.txt"}
        - {src: "org_crlf.txt", dest: "./hoge_crlf_to_crlf.txt"}
        - {src: "org_lf.txt",   dest: "./hoge_lf_to_lf.txt"}
        - {src: "org_lf.txt",   dest: "./hoge_lf_to_crlf.txt"}

    - name: CRLF to LF by replace
      replace:
        dest: "{{ item }}"
        regexp: '(.*)\r\n'
        replace: '\1\n'
      with_items:
        - "hoge_crlf_to_lf.txt"
        - "hoge_lf_to_lf.txt"

    - name: LF to CRLF by replace
      replace:
        dest: "{{ item }}"
        regexp: '(.*)[^\r]\n'
        replace: '\1\r\n'
      with_items:
        - "hoge_crlf_to_crlf.txt"
        - "hoge_lf_to_crlf.txt"

やってることは、用意したファイルをコピーしてregexpでそれぞれCRLF -> LF およびその逆の変換を行なっているだけです。

結果は以下のとおり。

$ ansible-playbook test.yml 
 [WARNING]: Host file not found: /usr/local/etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [127.0.0.1] ***************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [copy] ********************************************************************
changed: [127.0.0.1] => (item={u'dest': u'./hoge_crlf_to_lf.txt', u'src': u'org_crlf.txt'})
changed: [127.0.0.1] => (item={u'dest': u'./hoge_crlf_to_crlf.txt', u'src': u'org_crlf.txt'})
changed: [127.0.0.1] => (item={u'dest': u'./hoge_lf_to_lf.txt', u'src': u'org_lf.txt'})
changed: [127.0.0.1] => (item={u'dest': u'./hoge_lf_to_crlf.txt', u'src': u'org_lf.txt'})

TASK [CRLF to LF by replace] ***************************************************
changed: [127.0.0.1] => (item=hoge_crlf_to_lf.txt)
ok: [127.0.0.1] => (item=hoge_lf_to_lf.txt)

TASK [LF to CRLF by replace] ***************************************************
ok: [127.0.0.1] => (item=hoge_crlf_to_crlf.txt)
changed: [127.0.0.1] => (item=hoge_lf_to_crlf.txt)

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=4    changed=3    unreachable=0    failed=0   

$ file hoge_*
hoge_crlf_to_crlf.txt: ASCII text, with CRLF line terminators
hoge_crlf_to_lf.txt:   ASCII text
hoge_lf_to_crlf.txt:   ASCII text, with CRLF line terminators
hoge_lf_to_lf.txt:     ASCII text

というわけでめでたくreplaceモジュールで改行コードの変換ができたようです。
ターゲットマシンがwindowsになった時にregexpに指定している'\n'がLFとして解釈されるのか、CRLFとして解釈されるのか気にはなりますが、ちょっと今時間が無いのでここで一旦終了します。
もし知ってる方いたら教えてもらえると助かります。