1

Тема: JScript: поиск и замена текста по регулярным выражениям

Фильтр текста по регулярным выражениям (регэкспам). Работать с ним только через cscript.exe.

Обрабатывает переданный по конвейеру текст заданным регулярным выражением и
выводит в выходной поток.

Может следующее:
- вывести список подстрок, совпадающих с регулярным выражением.
- вывести текст, удалив текст, совпадающий с регулярным выражением (ключ "r")
- вывести текст, заменив текст, совпадающий с регулярным выражением
на свой текст (ключ "r") Поддерживаются переменные замены (match variables).

cscript.exe strfilt.js </регулярное выражение/[ключи]> [замена]

Помимо стандартных ключей WSH (i,m,g) введен новый ключ "r". Он указывает,
учитывать ли строку замены
Регулярное выражение или строка замены заключаются в кавычки, если в них есть пробелы.
Примеры:

echo 001234-5699 | cscript.exe strfilt.js "/(\d{4})\-(\d{2})/igr" "$2 = $1"
echo 001234-5699 | cscript.exe strfilt.js "/(\d{4})/i"
echo 001234-5699 | cscript.exe strfilt.js "/(\d{4})/ig"

Полное описание синтаксиса регулярных выражений можно найти в документации Microsoft по WSH:
http://download.microsoft.com/download/ … ript56.chm

Этот же хелп выдается, если запустить скрипт без параметров.

Я этот скрипт использую в EditPlus - там есть возможность обрабатывать открытый файл с помощью текстовых фильтров - утилит, которые принимают текст по конвейеру и выводят результат в stdout.

try {
   var WSH = new ActiveXObject ('WScript.Shell');
   var Arg = WScript.Arguments;
   var reg = new RegExp('.', '');
   var input = '';
   var repl  = '';
   var sr    = '';

// Если скрипт запущен через WScript, ругаемся и выходим
if (WScript.FullName.toLowerCase() == (WScript.Path+'\\wscript.exe').toLowerCase()) {
      WSH.Popup('Запуск сценария производится только через '+WScript.Path+'\\cscript.exe.\n\nВыходим...', 0, 'Ошибка', 16);
      WScript.Quit();
}

if (Arg.length == 0) {
      WScript.StdOut.WriteLine(
         'Фильтр текста по регулярным выражениям (регэкспам)\n\n'+
         'Обрабатывает переданный по конвейеру текст заданным регулярным выражением и\nвыводит в выходной поток.\n\n'+
         'Может следующее:\n'+
         '\t- вывести список подстрок, совпадающих с регулярным выражением.\n'+
         '\t- вывести текст, удалив текст, совпадающий с регулярным выражением (ключ "r")\n'+
         '\t- вывести текст, заменив текст, совпадающий с регулярным выражением\n\tна свой текст (ключ "r") Поддерживаются переменные замены (match variables).\n\n'+
         'cscript.exe '+WScript.ScriptName+' </регулярное выражение/[ключи]> [замена]\n\n'+
         'Помимо стандартных ключей WSH (i,m,g) введен новый ключ "r". Он указывает,\nучитывать ли строку замены\n'+
         'Регулярное выражение или строка замены заключаются в кавычки, если в них есть пробелы.\n'+
         'Примеры:\n\n'+
         'echo 001234-5699 | cscript.exe '+WScript.ScriptName+' "/(\\d{4})\\-(\\d{2})/igr" "$2 = $1"\n'+
         'echo 001234-5699 | cscript.exe '+WScript.ScriptName+' "/(\\d{4})/i"\n'+
         'echo 001234-5699 | cscript.exe '+WScript.ScriptName+' "/(\\d{4})/ig"\n\n'+
         'Полное описание синтаксиса регулярных выражений можно найти в документации Microsoft по WSH:\nhttp://download.microsoft.com/download/9/1/d/91dfd1b3-a274-4e17-a376-f605ff39c58c/script56.chm');
      WScript.Quit();
   }

   // из входных параметров вычленяем регулярное выражение, ключи к нему и строку замены (если указана)
   var re = Arg(0).match(/\/(.+)\/([imgr]{1,4})?/i)
   if (re) {
      // стандартные флаги Regexp Object - g (global) i (ignorecase) m (multiline)
      // вводим свой флаг - "r" (учитывать строку замены)
      var toRepl = (Arg.length>=2)?( Arg(1) ):(''); // строка замены для ключа "r"
      var isRepl = (re[2].search('r') >= 0);  // заменить найденное в тексте на содержимое третьего параметра.
                                               // Если третий параметр не указан, это равноценно удалению найденного
      var isBlk  = (re[2].search('m') < 0);   // искать не построчно а во всем тексте сразу
      var isGlob = (re[2].search('g') >= 0);  // g - глобальная замена

      re[2] = re[2].replace(/r/ig,'')+''; // поскольку наш ключ самопальный, выкидываем его, а то WSH им подавится

      reg.compile(re[1], re[2]); // Compiles a regular expression into an internal format for faster execution.
   } else {
      WSH.Popup("Регулярное выражение записано с ошибкой",0,'Ошибка выполнения',16+0);
      WScript.Quit();
   }

   if (isBlk){
      // обрабатывать весь текст одновременно
      while (!WScript.StdIn.AtEndOfStream) {
         input += WScript.StdIn.ReadAll();
      }
      Process(input)
   } else {
      // работать построчно
      while (!WScript.StdIn.AtEndOfStream) {
         input = WScript.StdIn.ReadLine();
         Process(input)
      }
   }
   input = null;

} catch(e) {
   WSH.Popup(e.description,0,'Ошибка выполнения',16+0);
}


function Process(){
   if (isRepl) {
      // заменять найденное
      WScript.StdOut.Write( input.replace(reg, toRepl) + ((!isBlk) ? '\n' : '') );
   } else {
      // вывести только найденное
      if ( sr = input.match(reg) ) {
         if (isGlob){
            // If the global flag is set, elements 0 - n contain all matches that occurred. (MS Help)
            // Выводим весь список совпавших подстрок
            for(var i=0; i<sr.length; i++) {
               WScript.StdOut.WriteLine(sr[i]);
            }
         } else {
            // If the global flag (g) is not set, Element zero of the array contains the entire match,
            // while elements 1 – n contain any submatches that have occurred within the match. (MS Help)
            // Выводим первую попавшуюся подстроку
            WScript.StdOut.WriteLine(sr[0]);
         }
      }
   }
}