【Photoshopスクリプト】レイヤーをRegexで一括リネームするスクリプトを作ってみた

## はじめに
選択しているレイヤーをまとめてリネームするようなPhotoshopスクリプトを作ってみました。
Regex(正規表現)が使えます。

## スクリプトの機能 : 特定の文字列を置換
選択中のレイヤーの中に含まれる「レイヤー」という文字をすべて「Layer」に置き換えるといった作業。
手作業でやると手間ですが、このスクリプトを使うと一発で置換できます。

![regex_rename.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/d95fb911-102d-de42-26de-1832e49cb82f.gif)



Regex Pattern の部分に ```レイヤー```
Replacementの部分には ```Layer```を入力した状態で　リネーム実行することでまとめて置き換わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/05ac20ef-4787-bfbb-e9bc-6447dc8b7219.png)


## スクリプトの機能 : 正規表現で半角整数を削除
レイヤー名に含まれる半角数字を削除する、といったこともできます。

![replace_number.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/fe6cfd8d-884e-77e0-d8ea-82321950696a.gif)


Regex Pattern の部分に ```[0-9]```
Replacementの部分には 何も入力しない状態で　リネーム実行。

```[0-9]``` にマッチする文字(1ケタの半角整数)が空文字に置き換わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/e13ec83b-9c53-84d6-c35b-348de9f80bec.png)

2ケタ以上の半角整数にもマッチさせたい場合は```[0-9]+```を指定します。

## Photoshopスクリプト
```regex_rename_layer.jsx
// ボタン
var BUTTON_LABEL = "リネーム実行"; // ボタン文字
var BUTTON_SIZE_X = 180;
var BUTTON_SIZE_Y = 32;
var BUTTON_SPACE_UP = 15;

// フィールド
var STATIC_TEXT_FIELD_SIZE_X = 75;
var EDIT_TEXT_FIELD_SIZE_X = 200;
var FIELD_SIZE_Y = 20;
var FIELD_SPACE_X = 10.0;
var FIELD_SPACE_Y = 10.0;

// マージン
var MARGIN_TOP = 12;
var MARGIN_BOTTOM = 15;
var MARGIN_LEFT = 15;
var MARGIN_RIGHT = 15;

// ウィンドウ 大きさ
var WINDOW_SIZE_X = MARGIN_LEFT + EDIT_TEXT_FIELD_SIZE_X + FIELD_SPACE_X + STATIC_TEXT_FIELD_SIZE_X + MARGIN_RIGHT;
var WINDOW_SIZE_Y = MARGIN_TOP + FIELD_SIZE_Y * 2 + FIELD_SPACE_Y * 2 + BUTTON_SIZE_Y + MARGIN_BOTTOM + BUTTON_SPACE_UP;

var selectedLayers = getSelectedLayers(app.activeDocument); // 選択中のレイヤー
main();

/////////////////////////////////////////////////////////////////////////////////////
// メインの処理
/////////////////////////////////////////////////////////////////////////////////////
function main() {
    if (selectedLayers.length == 0) {
        alert("レイヤーが選択されていません");
        return;
    }

    // テキスト左上の位置
    var posX = MARGIN_LEFT;
    var posY = MARGIN_TOP;

    var uDlg = new Window('dialog', 'Regexリネーム', [0, 0, WINDOW_SIZE_X, WINDOW_SIZE_Y]);
    uDlg.center();

    // 上側
    posX = MARGIN_LEFT;
    uDlg.add("statictext", [posX, posY, posX + STATIC_TEXT_FIELD_SIZE_X, posY + FIELD_SIZE_Y], "Regex Pattern")
    posX += STATIC_TEXT_FIELD_SIZE_X + FIELD_SPACE_X;

    var regexPatternText = uDlg.add("edittext", [posX, posY, posX + EDIT_TEXT_FIELD_SIZE_X, posY + FIELD_SIZE_Y], selectedLayers[0].name);

    // 下側
    posY += FIELD_SIZE_Y + FIELD_SPACE_Y;
    posX = MARGIN_LEFT;
    uDlg.add("statictext", [posX, posY, posX + STATIC_TEXT_FIELD_SIZE_X, posY + FIELD_SIZE_Y], "Replacement");
    posX += STATIC_TEXT_FIELD_SIZE_X + FIELD_SPACE_X;
    var regexReplacementText = uDlg.add("edittext", [posX, posY, posX + EDIT_TEXT_FIELD_SIZE_X, posY + FIELD_SIZE_Y], "");

    // ボタン
    var buttonPosX = WINDOW_SIZE_X / 2 - BUTTON_SIZE_X / 2;
    posY += FIELD_SIZE_Y + FIELD_SPACE_Y + BUTTON_SPACE_UP;
    uDlg.okBtn = uDlg.add("button", [buttonPosX, posY, buttonPosX + BUTTON_SIZE_X, posY + BUTTON_SIZE_Y], BUTTON_LABEL, { name: "ok" });
    uDlg.okBtn.onClick = function () { // ボタンを押したときの処理
        DoRenameLayers(regexPatternText.text, regexReplacementText.text);
        uDlg.close();
    }

    // ダイアログ表示
    uDlg.show();
}

/////////////////////////////////////////////////////////////////////////////////////
// Regexを利用したレイヤーのリネーム実行
/////////////////////////////////////////////////////////////////////////////////////
function DoRenameLayers(patternStr, replacementStr) {
    var docRef = app.activeDocument; // 現在開いているドキュメント
    var pattern = new RegExp(patternStr);
    for (var i = 0; i < selectedLayers.length; i++) {
        selectedLayers[i].selected = true;
        docRef.activeLayer = selectedLayers[i];

        docRef.activeLayer.name = docRef.activeLayer.name.replace(pattern, replacementStr); // 正規表現を利用したリネーム
    }

    alert("リネーム完了しました");
}

/////////////////////////////////////////////////////////////////////////////////////
// Thanks to hilukasz/Selected_layers-PS.jsx
// https://gist.github.com/hilukasz/03b17ee78414aadff995
/////////////////////////////////////////////////////////////////////////////////////
function newGroupFromLayers(doc) {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putClass(sTID('layerSection'));
    desc.putReference(cTID('null'), ref);
    var lref = new ActionReference();
    lref.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    desc.putReference(cTID('From'), lref);
    executeAction(cTID('Mk  '), desc, DialogModes.NO);
};

function undo() {
    executeAction(cTID("undo", undefined, DialogModes.NO));
};

function getSelectedLayers(doc) {
    var selLayers = [];
    newGroupFromLayers();

    var group = doc.activeLayer;
    var layers = group.layers;

    for (var i = 0; i < layers.length; i++) {
        selLayers.push(layers[i]);
    }

    undo();

    return selLayers;
};

function cTID(s) { return app.charIDToTypeID(s); };
function sTID(s) { return app.stringIDToTypeID(s); };
```

## 正規表現を実行している箇所(抜粋)

```regex_rename_layer.jsx

/////////////////////////////////////////////////////////////////////////////////////
// Regexを利用したレイヤーのリネーム実行
/////////////////////////////////////////////////////////////////////////////////////
function DoRenameLayers(patternStr, replacementStr) {
    var docRef = app.activeDocument; // 現在開いているドキュメント
    var pattern = new RegExp(patternStr);
    for (var i = 0; i < selectedLayers.length; i++) {
        selectedLayers[i].selected = true;
        docRef.activeLayer = selectedLayers[i];

        docRef.activeLayer.name = docRef.activeLayer.name.replace(pattern, replacementStr); // 正規表現を利用したリネーム
    }

    alert("リネーム完了しました");
}
```

## 参考
選択中のレイヤーを取得するJSXは下記URLのものを拝借させていただきました。

hilukasz/Selected_layers-PS.jsx
https://gist.github.com/hilukasz/03b17ee78414aadff995