アットウィキロゴ

スクリプト畑

基本JavaScript。時々Perl

  1. サクラエディタマクロ
  • かたっぱしからGrep
textに書いた条件のGrep結果をひたすら追記する。
GrepにはWindowsのFinsStrコマンドを利用。
やりすぎ注意

MAX_LINE = 10;
CRLF = "\r\n";
switch(Editor.GetLineCode()) {
case 1: CRLF = "\n"; break;
case 2: CRLF = "\r"; break;
}

while(1) {
var path = [];
var mode = "";
var matcher = [];
var exp = [];
var case_flag = false;
var regexp_flag = false;
var result_row = 0;
var err_flag = false;
//**************************************************************************
// 編集中ファイルから検索条件パラメータを取得する
//**************************************************************************
for(var i = 1; i <= Editor.GetLineCount(0); i++) {	// 行をループ
	// 1行取得
	var str = Editor.GetLineStr(i);
	// 行頭と行末の余分なスペースをけずる
	str = str.replace(/^\s*(.*?)\s*?$/, "$1");
	// コメント(#)を削る
	str = str.replace(/#.*$/, "");
	if(str == null || str.length == 0) continue;
	// []で囲まれた文字の取得
	if(str.match(/^\[(\w+)\]$/)) {
		// []の中身の文字を英小文字で前後のスペースを削って取得
		mode = RegExp.$1.toLowerCase().replace(/^\s*(.*?)\s*?$/, "$1")
		continue;
	}
	
	// []で囲まれていない場合
	switch(mode) {
	case ""      : break;	// まだ[]タグがないので放置して次へ
	case "folder":
	case "path"  :
	case "dir"   : path.push(str); break;	// パス指定取得
	case "expand":
	case "exp"   : exp.push(str);  break;	// 拡張子取得
	case "find"  :
	case "search":
	case "match" : matcher.push(str); break;	// 検索文字列取得
	case "hilow" : case_flag = true;  break;	// 大文字小文字区別なし
	case "regexp":
	case "reg"   : regexp_flag = true; break;	
	case "result":								// 検索実施済み?
		if(result_row == 0) result_row = i;		// 場所を把握。
		break;
	default      : err_flag = true;   break;	// それ以外はエラー
	}
}
// 拡張子が指定されていないときのデフォルト
if(exp.length == 0) exp.push("*");

// ファイルの末尾に移動
Editor.GoFileEnd();

if(path.length == 0 || matcher.length == 0 || err_flag) {
	// パラメータが足りない場合使い方を挿入してしまう。
	Editor.InsText(CRLF);
	Editor.InsText("[match]" + CRLF + CRLF);
	Editor.InsText("# ここに検索文字を羅列する" + CRLF + CRLF);
	Editor.InsText("[dir]" + CRLF + CRLF);
	Editor.InsText("# ここに検索対象のパスを羅列する" + CRLF + CRLF);
	Editor.InsText("[exp]" + CRLF + CRLF);
	Editor.InsText("# ここに検索対象のファイルを羅列する" + exp + CRLF + CRLF);
	Editor.InsText("#[hilow] # 大文字小文字を区別しない場合指定する" + CRLF);
	break;
}
if(result_row > 1) {
	var btn = Editor.YesNoBox("結果がすでに存在します。削除して上書きしますか?") 
	if(btn == null || btn == 0|| btn == 2 || btn == 3 || btn == 7) {
		break;
	}
	Editor.Jump(result_row - 1);
	Editor.GoLineTop(1);
	Editor.BeginSelect();
	Editor.GoFileEnd_Sel();
	Editor.Delete();
}
// Resultタグ出力
Editor.InsText(CRLF + "[Result]" + CRLF);

// 検索開始時のファイル最終位置を保存する。
var result_row = Editor.GetLineCount(0);

//**************************************************************************
// 検索本体
//**************************************************************************
for(var j = 0; j < matcher.length; j++) { // 検索文字ループ
	// 検索文字列出力
	Editor.InsText("■■■■■■■■検索文字列:" + matcher[j] + "\t検索ファイルの拡張子:" + exp.join(","));
	if(case_flag) Editor.InsText("\t大文字小文字を区別しない");
	Editor.InsText(CRLF);
	
	// 外部プログラム(windows標準コマンド利用)
	var exec = "findstr /s /n /C:\"" + matcher[j] + "\"";
	if(case_flag) exec += " /i"		// 英大文字と英小文字を区別しない
	if(regexp_flag) exec += " /r"	// 正規表現
	// %Aはのfor文の結果
	exec += " /D:"+ path.join(";") + " " + exp.join(" ");
	
	// ファイルの末尾に移動(コマンド実行中にカーソルが手で移動できてしまうので)
	Editor.GoFileEnd();
	
	// 今の最終ファイル位置を保存
	var befor_editorline = Editor.GetLineCount(0);

	Editor.ExecCommand(exec, 3); // 実行
	
	// ファイルの末尾に移動(コマンド実行中にカーソルが手で移動できてしまうので)
	Editor.GoFileEnd();
	// 最終ファイル位置が変わらないときはキャンセル
	if(befor_editorline == Editor.GetLineCount(0))	break;
}
break;
}

  • FindStrの出力をタグファイルへ変換
↑の結果をタグジャンプできるように変換するスクリプト

MAX_LINE = 10;
CRLF = "\r\n";
switch(Editor.GetLineCode()) {
case 1: CRLF = "\n"; break;
case 2: CRLF = "\r"; break;
}

while(1) {
// 今の位置取得
var result_row = Editor.ExpandParameter("$y");
//**************************************************************************
// FindStrの出力方式を普通のGrep方式(タグジャンプ対応)に変換します。
//**************************************************************************
// 検索完了後の最終ファイル位置を保存する。
var end_line = Editor.GetLineCount(0);
// 記録していた位置へカーソル移動
Editor.Jump(result_row);

// FindStrの検索したパス。
var path_str = "";
// FindStr実施行の正規表現
var reFindStr  = new RegExp("^.+?findstr +?/s +?/n +?/C:.+? +?/D.+? .+$");
// FindStrが出力する検索結果行
var reResult = new RegExp(":(\\d+):\\s*");

while(1) {
	// 今の最終ファイル位置を保存
	var befor_editorline = Editor.GetLineCount(0);
	// 1行取得
	var str = Editor.GetLineStr(0);
	// 末尾の改行記号を削除
	str = str.replace(/[\r\n]+$/, "");
	var del_flag = false;
	// 先頭にスペース2文字があるかつ、末尾が:の行がFindStrのパス出力。
	if(str.match(/^  (.*?):$/)) {
		path_str = RegExp.$1;	// パス取得
		del_flag = true;
	}
	// 改行のみの行か、FindStr実施行ならいらない行
	if(del_flag || str == null || str.length == 0 || reFindStr.exec(str) != null) {
		Editor.DeleteLine();	// この行はいらないので消す
		// 行削除済みなのでrowはカウントしたくないのでそのまま繰り返し
	} else {
		// 検索文字列行かを判別
		if(str.match(/^■■■■■■■■検索文字列:/)) {
			Editor.Down();	// 検索文字列行は残す
		} else {
			// それ以外は検索結果。
			Editor.DeleteLine();	// 一旦消す。
			// ファイル位置との区切り記号をタブ区切に(エクセル貼り付け用)
			str = str.replace(reResult, "\t$1\t");
			// FindStrのパスを付加
			if(path_str != null && path_str.length > 0) Editor.InsText(path_str + "\\");
			Editor.InsText(str + CRLF);	// 貼り付け治す
		}
		result_row++;	// 次の行へ
	}
	if(befor_editorline < Editor.GetLineCount(0)) break;	// 暴走防止用
	if(Editor.GetLineCount(0) <= result_row) break;	// 最終行なら終了
}
break;
}

  • 検索して一致した文字がある行を削除
目的不明・・・private methodを消すとかに使ったのか?

var start_line = 1;
var end_line = Editor.GetLineCount(0); //論理行数を取得
CRLF = "\r\n";
switch(Editor.GetLineCode()) {
case 1: CRLF = "\n"; break;
case 2: CRLF = "\r"; break;
}

if(Editor.IsTextSelected != 0) {
// 選択状態なら先頭行と末尾行を取得
start_line = Editor.GetSelectLineFrom();
end_line = Editor.GetSelectLineTo();
// レイアウト行から論理行へ変換
start_line = Editor.LayoutToLogicLineNum(start_line)
end_line = Editor.LayoutToLogicLineNum(end_line)
}

while(1) {
var mth = Editor.InputBox("検索結果のある行を削除します。検索文字を指定してください", "", 64);
if(mth == null || mth == "") break;
var m = new RegExp(mth, 'i');
Editor.Jump(start_line);
for(var i = start_line; i <= end_line; ) {	// 行をループ
	var str = Editor.GetLineStr(0);		// 1行取得

	str = str.replace(/[\r\n]+$/, "");
	if(str.match(m)) {	Editor.DeleteLine();	end_line--;	}
	else {	Editor. Down();	i++;	}
}
break;
}

  1. WSH(EXCELやCSVをADOで操作)
JOINができないのが痛い。。。

  • C#のソースからnamespace/class/methodの一覧を作成(csv)する。
関数が現れた場所と、コメントのようなものも表になる。
エクセルにソース一覧を作っとかないとダメだし、SJIS以外はダメだが。

var path = "C:\\Users\\takahara.kosuke\\Documents";
var file = "PS全検索結果.xlsx";
var outfile_name = "関数一覧.csv";

var regComment = /\/\*.*\*\//g;
var regMethod = /(([A-Za-z][0-9A-Za-z:\.\[\]]*\s+)+[A-Za-z][0-9A-Za-z:\[\]]*\s*)\(/;

comment = "";
line_buf = 0;
String.prototype.dqe = function() {
var ret = '"';
for(var i = 0; i < this.length; i++) {
	var c = this.charAt(i);
	ret += c;
	if(c == '"') ret += c;
}
return ret + '"';
};
String.prototype.trim = function() {
return this.replace(/^\s*(.*?)\s*$/g, "$1");
};
String.prototype.lineCommentDelete = function() {
var ret = this.replace(/#.*$/, "").replace(/\/\/(.*)$/, "");
comment += RegExp.$1;
// 予約語で始まるものは消す
return ret.trim().replace(/^(this\.|(new|using|else|return|for|switch|while|if|do)\s).*$/g, "");
};
String.prototype.tipMatch = function(reg) {
var ret = {result: false, string : "", note : ""};
// コメントの中身を退避
var arr = this.match(regComment);
if(arr) {
	for(var i in arr) {
		comment += ("" + arr[i]).substr(2, arr[i].length - 4).trim();
	}
}
var str = this.replace(regComment, "").trim();
if(str.match(/^\/\*/)) {	// 間違ってコメントの中で止まってる。
	comment += RegExp.rightContext.trim();
	return ret;
}
	
str = str.replace(/^.*\}/g, "").replace(/\{.*$/, "").trim().replace(/^\[.*\]/, "").trim();
if(str.length < 2) return ret;

var flag = str.match(reg);
if(!flag) return ret;
var str = RegExp.lastMatch + RegExp.rightContext;
ret = {result: true, string: str.trim(), note: comment.replace(/^.*\}/g, "").replace(/\{.*$/, "").replace(/[=\/\*\-#]+/g, "").trim()};
comment = "";
return ret;
};

var driver = "Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)"
var readonry = true;

var fso = new ActiveXObject("Scripting.FileSystemObject")
var log = fso.CreateTextFile(path +"\\"+outfile_name+".log", true);

var xls = new ActiveXObject("ADODB.Connection");

xls.Open("Driver={" + driver + "}; DBQ=" + path +"\\" + file + ";ReadOnly=" + (readonry ? 1: 0));

var outfile = fso.CreateTextFile(path +"\\" + outfile_name, true);
outfile.WriteLine("No,ソース,資源,資源タイプ,場所,コメント");

var count = 0;

var sql = "SELECT [ソース] AS Src FROM [ソース一覧$]";
var rs = xls.Execute(sql);

for(; !rs.Eof; rs.MoveNext()) {
var src = new String(rs("Src"));
if(src == null || src.length == 0) continue;
// ソースを開く
var frs = fso.OpenTextFile(src, 1);
comment = "";
line_buf = 0;
var line = 0;
var buf = "";
// ソースの最後までループ
while(!frs.AtEndOfStream) {
	line++;	// ソース内の行数
	// ソールから1行読みコメントっぽいところを削ってバッファに足す
	buf += frs.ReadLine().lineCommentDelete();
	if(buf.length > 0 && line_buf == 0) line_buf = line;
	// 末端記号(;)があるところは要らない
	if(buf.indexOf(";") >= 0) {
		buf ="";
		line_buf = 0;
		continue;
	}
	// ブロックの開始以外はバッファに足すだけ
	if(buf.indexOf("{") < 0) continue;
	
	// メソッドっぽい
	var e = buf.tipMatch(regMethod);
	if(e.result) e.type = "function";
	else {
	// クラスっぽい
		e = buf.tipMatch(/\s*class\s+\w+/);
		if(e.result) {
			e.string = e.string.replace(/\s*:.*$/, "");
			e.type = "class";
		} else {
			// ネームスペースっぽい
			e = buf.tipMatch(/\s*namespace\s+\w+/);
			if(e.result) e.type = "namespace";
		}
	}
	if(e.result) {
		count++;
		outfile.WriteLine(
			[count, src.dqe(), e.string.dqe(), e.type, line_buf, e.note.dqe()].join(","));
	}
	buf = ""
	comment ="";
	line_buf = 0;
}
// ソースを閉じる
frs.Close();
frs = null;

}
rs.Close();
rs = null;

xls.Close();
xls = null;

outfile.Close();
outfile = null;

fso = null;

var wsh = WScript.CreateObject("WScript.Shell")
wsh.Popup("完了しました", 5, outfile_name, 0 + 64)
wsh = null;

  • 使用パターン一覧を作る。
縦にGrep結果、横にパターン1・2・・・・みたいな表を作ってしまったのでこれをまとめるためのもの。
まあUNIONで集計してるだけだが。

String.prototype.dqe = function() {
var ret = '"';
for(var i = 0; i < this.length; i++) {
	var c = this.charAt(i);
	ret += c;
	if(c == '"') ret += c;
}
return ret + '"';
}

var output = "GROUP.csv";

var excel_driver = "Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)"
var path = "C:\\Users\\takahara.kosuke\\Documents";
var file = "PS全検索結果.xlsx";
var csv_driver = "Microsoft Text Driver (*.txt; *.csv)"
var xls_readonry = true;
var csv_readonry = false;

var sql;
var line;
var str;
var func = [];

var fso = new ActiveXObject("Scripting.FileSystemObject")
var log = fso.CreateTextFile(path +"\\wsh.log", true);

var xls = new ActiveXObject("ADODB.Connection");
var csv = new ActiveXObject("ADODB.Connection");

xls.Open("Driver={" + excel_driver + "}; DBQ=" + path +"\\" + file + ";ReadOnly=" + (xls_readonry ? 1: 0));
csv.Open("Driver={" + csv_driver + "}; DBQ=" + path + ";ReadOnly=" + (csv_readonry ? 0: 1));


sql = "SELECT Top 1 * FROM [計画修正のみ$]"
var rs = xls.Execute(sql);
var max = 0;
var ar = [];
for(var i = 0; i < rs.Fields.Count; i++) {
var name = new String(rs.Fields(i).Name);
if(name.match(/^パターン(\d+)$/)) {
	var m = parseInt(RegExp.$1);
	if(max < m) max = m;
}
}
rs.Close();

var ws = fso.CreateTextFile(path +"\\" + output, true);
sql = "";
for(var i = 0; i < max; i++) {
var type = "分類" + (i+1);
var pattern = "パターン" + (i+1);
if(i>0) sql += " UNION ";
sql += "SELECT [" + type + "] AS T, [" + pattern + "] AS P FROM [計画修正のみ$]";
}
sql += " ORDER BY T ASC, P ASC";

WScript.Echo(sql);
rs = xls.Execute(sql);
for(; !rs.Eof; rs.MoveNext()) {
	ws.WriteLine('"'+rs("T")+'","'+rs("P")+'"');
}



rs.Close();
rs = null;

ws.Close();
ws = null;

xls.Close();
xls = null;
csv.Close();
csv = null;

log.Close();
log = null;
fso = null;

  • 上の二つを集計してピポットで使えるようにする。
もうなんだ、一斉Grepに戻ってないか?

var output = "サマリ.csv";
var path = "C:\\Users\\takahara.kosuke\\Documents";
var file = "PS全検索結果.xlsx";

var wsh = WScript.CreateObject("WScript.Shell")

String.prototype.dqe = function() {
var ret = '"';
for(var i = 0; i < this.length; i++) {
	var c = this.charAt(i);
	ret += c;
	if(c == '"') ret += c;
}
return ret + '"';
}

var excel_driver = "Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)"
var csv_driver = "Microsoft Text Driver (*.txt; *.csv)"
var readonry = true;

var sql;
var l;
var func = [];

var fso = new ActiveXObject("Scripting.FileSystemObject")
var log = fso.CreateTextFile(path +"\\wsh.log", true);

var xls = new ActiveXObject("ADODB.Connection");
var rs;

xls.Open("Driver={" + excel_driver + "}; DBQ=" + path +"\\" + file + ";ReadOnly=" + (readonry ? 1: 0));

sql = "SELECT [ソース], [資源], [資源タイプ], [場所] FROM [資源一覧$]";
for(rs = xls.Execute(sql); !rs.Eof; rs.MoveNext()) {
var src = rs("ソース");
if(!(src in func)) func[src] = [];
func[src].push({object: new String(rs("資源")), type: new String(rs("資源タイプ")), line: new String(rs("場所"))});
}
rs.Close();
rs = null;


var pattern = [];
sql = "SELECT [#] AS N, [分類] AS T, [パターン] AS P FROM [使用パターン一覧$]";
for(rs = xls.Execute(sql); !rs.Eof; rs.MoveNext()) {
pattern[rs("P")] = {
	'No': parseInt(rs("N")),
	'Type' : new String(rs("T"))
}
}


sql = "SELECT Top 1 * FROM [計画修正のみ$]"
rs = xls.Execute(sql);
var max = 0;
var ar = [];
for(var i = 0; i < rs.Fields.Count; i++) {
var name = new String(rs.Fields(i).Name);
if(name.match(/^パターン(\d+)$/)) {
	var m = parseInt(RegExp.$1);
	if(max < m) max = m;
}
}
rs.Close();
rs = null;

sql = ""
for(var i = 0; i < max; i++) {
if(i > 0) sql += " UNION ALL ";
sql += "SELECT [No], [フォルダ], [ソース], [行], [列], [コード],[パターン" + (i+1) + "] AS P";
sql += " FROM [計画修正のみ$]"
}

var btn = wsh.Popup(sql, 10, "実行します", 1 + 64)
if(btn == 1) {

var ws = fso.CreateTextFile(path +"\\" + output, true);
ws.WriteLine("No,ソース,行,列,コード,分類No,分類,パターン,クラス,クラス行,関数,関数行");

for(rs = xls.Execute(sql); !rs.Eof; rs.MoveNext()) {
	var ptn  = new String(rs("P"));
	if(!ptn) continue;
	if(ptn.length < 2) continue;
	
	l = parseInt(rs("行"));
	var src  = new String(rs("ソース"));
	var code = new String(rs("コード"));
	var src_file = "z:\\" + rs("フォルダ") + "\\" + rs("ソース");
	var parm = {
		no: 0,
		type: "-",
		function_t: {line: 0, str: ""},
		class_t:    {line: 0, str: ""}
	};
	if(ptn in pattern) {
		parm.no = pattern[ptn].No;
		parm.type = pattern[ptn].Type;
	}
	if(!parm.no) continue;


	for(var j in func[src_file]) {
		if(func[src_file][j].line > l) break;
		if(func[src_file][j].type == "function") {
			parm.function_t.str   = func[src_file][j].object;
			parm.function_t.line  = func[src_file][j].line;
		} else
		if(func[src_file][j].type == "class") {
			parm.class_t.str   = func[src_file][j].object;
			parm.class_t.line  = func[src_file][j].line;
		}
	}
	
	ws.WriteLine([
		rs("No"), src.dqe(), l, rs("列"), code.dqe(),
		parm.no, parm.type.dqe(), ptn.dqe(),
		parm.class_t.str.dqe(), parm.class_t.line,
		parm.function_t.str.dqe(), parm.function_t.line
		].join(','));
}
rs.Close();
rs = null;

ws.Close();
ws = null;

wsh.Popup("完了しました", 10, output, 0 + 64)
wsh = null;
}
xls.Close();
xls = null;

log.Close();
log = null;
fso = null;


  • JOINができないので手動でJOIN
あほすぎるが・・・

var path = "C:\\Users\\takahara.kosuke\\Documents";
var file = "PS全検索結果.xlsx";
var outfile_name = "クラス一覧.csv";

comment = "";
line_buf = 0;
String.prototype.dqe = function() {
var ret = '"';
for(var i = 0; i < this.length; i++) {
	var c = this.charAt(i);
	ret += c;
	if(c == '"') ret += c;
}
return ret + '"';
};
String.prototype.trim = function() {
return this.replace(/^\s*(.*?)\s*$/g, "$1");
};

var driver = "Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)"
var readonry = true;

var fso = new ActiveXObject("Scripting.FileSystemObject")
var log = fso.CreateTextFile(path +"\\"+outfile_name+".log", true);

var xls = new ActiveXObject("ADODB.Connection");

xls.Open("Driver={" + driver + "}; DBQ=" + path +"\\" + file + ";ReadOnly=" + (readonry ? 1: 0));

var outfile = fso.CreateTextFile(path +"\\" + outfile_name, true);
outfile.WriteLine("No,ソース,行,クラス,コメント");

var count = 0;

var sql = "SELECT [No],[クラス] FROM [クラス一覧$]";
var rs;
for(rs = xls.Execute(sql); !rs.Eof; rs.MoveNext()) {
var sql = "SELECT [ソース], [場所], [コメント] FROM [資源一覧$]"
	+ " WHERE [資源タイプ] = 'class' AND [資源] = '" + rs("クラス") + "'";
var rss;
for(rss = xls.Execute(sql); !rss.Eof; rss.MoveNext()) {
	outfile.WriteLine(
		[rs("No"), String(rss("ソース")).dqe(), String(rs("クラス")).dqe(), rss("場所"), String(rss("コメント")).dqe()].join(","));
}
rss.Close();
rss = null;
}
rs.Close();
rs = null;

xls.Close();
xls = null;

outfile.Close();
outfile = null;

fso = null;

var wsh = WScript.CreateObject("WScript.Shell")
wsh.Popup("完了しました", 5, outfile_name, 0 + 64)
wsh = null;
最終更新:2013年04月03日 17:03