批处理:如何存储正则表达式搜索期间遇到的值&替换(repl.bat)

时间:2014-11-04 23:23:08

标签: batch-file replace store batch-processing

使用Batch,我正在寻找一种方法来(1)搜索正则表达式模式和(2)在该模式中存储变量......所以我可以在进行搜索和替换时使用这些变量。

我一直在使用由@dbenhamoriginal REPL.BAT postearliest StackOverflow post)创建的REPL.BAT。以下是该场景的一个示例。

我搜索文档以查找以下代码:

driver.find_element_by_id("username").send_keys("rwbyrd")
driver.find_element_by_id("password").send_keys("password")

并将其替换为......

login("rwbyrd","password")

使用以下批处理代码:

type %filename% | repl "\sdriver\.find_element_by_id\(\x22username\x22\)\.send_keys\(\x22rwbyrd\x22\)\s*driver\.find_element_by_id\(\x22password\x22\)\.send_keys\(\x22password\x22\)"       "login(\x22rwbyrd\x22,\x22password\x22)" MX >%filename%.new

注意:\ x22 =双引号的十六进制

我正在寻找的是一种存储[用户名]' rwbyrd'和[密码]'密码'来自代码I的值搜索&在进行替换时使用这些值。我想在REPL.BAT命令中找到一种方法来实现这一点,但我会采取我能得到的:)。有谁知道如何实现这一目标?提前谢谢!

2 个答案:

答案 0 :(得分:2)

使用正则表达式时,必须注意\s元字符匹配"任何空白字符。这包括空格,制表符和换页符。",但不是CR + LF对的行尾字符,因此您必须将它们包含在正则表达式中。

存在另一个类似于dbenham的REPL.BAT的程序;它被称为FindRepl.bat,您可以从this site下载它。在FindRepl替换字符串中,您可以包含$ 1,$ 2等,以获取匹配的"子表达式的值#34;括在括号中。例如,此输入文件:

Any previous line
    driver.find_element_by_id("username").send_keys("rwbyrd")
    driver.find_element_by_id("password").send_keys("password")
any posterior line

...通过以下行与FindRepl.bat一起处理:

type filename.txt | findrepl /Q:' "\sdriver\.find_element_by_id\('username'\)\.send_keys\('(.*)'\)\r\n\s*driver\.find_element_by_id\('password'\)\.send_keys\('(.*)'\)" "login('$1','$2')"

...产生这个输出:

Any previous line
   login("rwbyrd","password")
any posterior line

您可以测试相同的正则表达式是否在REPL.BAT中生成相同的输出。

PS - 我强烈建议您查看FindRepl /?建议的正则表达式文档。


编辑:我借用了dbenham的答案评论中所述的想法,并使用它通过我的FindRepl.bat中的替换文本中放置的JScript表达式来实现匹配的子字符串的处理程序;这样做的唯一要求是包含new / J(JScript表达式)开关并正确写入替换表达式。

程序中的修改相对简单,只需要5行行,其中包括2行新文档;我使用this site的示例作为基础来完成修改。下面的列表是通过fc /N FindRepl.bat "FindRepl Modified.bat"命令比较FindRepl.bat程序的原始版本和新版本的结果:

Comparing files FindRepl.bat and FINDREPL MODIFIED.BAT
***** FindRepl.bat
   28:  FINDREPL [/I] [/V] [/N] rSearch [/E:rEndBlk] [/O:s:e] [/B:rBlock] [/$:s1...]
   29:           [[/R] [/A] sReplace] [/Q:c] [/S:sSource]
   30:  
***** FINDREPL MODIFIED.BAT
   28:  FINDREPL [/I] [/V] [/N] rSearch [/E:rEndBlk] [/O:s:e] [/B:rBlock] [/$:s1...]
   29:           [[/R] [{/J|/A}] sReplace] [/Q:c] [/S:sSource]
   30:  
*****

***** FindRepl.bat
   39:    /R         Prints only replaced lines, instead of all file lines.
   40:    /A         Specifies that sReplace has alternative values matching rSearch.
***** FINDREPL MODIFIED.BAT
   39:    /R         Prints only replaced lines, instead of all file lines.
   40:    /J         Specifies that sReplace is a JScript expression, not a string.
   41:    /A         Specifies that sReplace has alternative values matching rSearch.
*****

***** FindRepl.bat
   48:  The replacement string may use $ to retrieve saved submatched substrings. See:
   49:  http://msdn.microsoft.com/en-us/library/t0kbytzc(v=vs.84).aspx
   50:  Use /A switch to insert several values separated by pipe in rSearch/sReplace.
***** FINDREPL MODIFIED.BAT
   49:  The replacement string may use $ to retrieve saved submatched substrings. See:
   50:  http://msdn.microsoft.com/en-us/library/t0kbytzc(v=vs.84).aspx   If /J switch
   51:  is given, the replacement text is an expression that must use submatched $.
   52:  Use /A switch to insert several values separated by pipe in rSearch/sReplace.
*****

***** FindRepl.bat
   89:  // FINDREPL [/I] [/V] [/N] rSearch [/E:rEndBlk] [/O:s:e] [/B:rBlock] [/$:s1...]
   90:  //          [[/R] [/A] sReplace] [/Q:c] [/S:source]
   91:  
***** FINDREPL MODIFIED.BAT
   91:  // FINDREPL [/I] [/V] [/N] rSearch [/E:rEndBlk] [/O:s:e] [/B:rBlock] [/$:s1...]
   92:  //          [[/R] [{/J|/A}] sReplace] [/Q:c] [/S:source]
   93:  
*****

***** FindRepl.bat
  105:      justReplaced = options.Exists("R"),
  106:      replace      = undefined,
***** FINDREPL MODIFIED.BAT
  107:      justReplaced = options.Exists("R"),
  108:      JSexpr       = false,
  109:      replace      = undefined,
*****

***** FindRepl.bat
  159:     if ( quote != undefined ) replace = replace.replace(eval("/"+quote+"/g"),'"');
  160:     if ( options.Exists("A") ) {  // Enable alternation replacements from "Se|ar|ch" to "Re|pla|ce"
  161:        var Asearch = search.split("|"),
***** FINDREPL MODIFIED.BAT
  162:     if ( quote != undefined ) replace = replace.replace(eval("/"+quote+"/g"),'"');
  163:     if ( options.Exists("J") ) {  // Replacement text is a JScript expression with the return value of function($0,$1,$2)
  164:        JSexpr = true;
  165:     } else if ( options.Exists("A") ) {  // Enable alternation replacements from "Se|ar|ch" to "Re|pla|ce"
  166:        var Asearch = search.split("|"),
*****

***** FindRepl.bat
  335:           if ( match(fileContents[lineNumber-1],search) ) {
  336:              WScript.Stdout.WriteLine(fileContents[lineNumber-1].replace(search,replace));
  337:              result++;
***** FINDREPL MODIFIED.BAT
  340:           if ( match(fileContents[lineNumber-1],search) ) {
  341:              WScript.Stdout.WriteLine(fileContents[lineNumber-1].replace(search,JSexpr?function($0,$1,$2){return(eval(replace))}:replace));
  342:              result++;
*****

***** FindRepl.bat
  345:     } else {  // Replace on entire file
  346:        WScript.Stdout.Write(fileContents.replace(search,replace));
  347:     }
***** FINDREPL MODIFIED.BAT
  350:     } else {  // Replace on entire file
  351:        WScript.Stdout.Write(fileContents.replace(search,JSexpr?function($0,$1,$2){return(eval(replace))}:replace));
  352:     }
*****

上一个列表应该足以获得FindRepl.bat的修改版本。这样,为了将第一个匹配的子表达式替换为大写字母,只需使用:

type filename | findrepl "(.*)" /J "$1.toUpperCase()"

此功能非常强大,因为替换文本可能是任何有效的JScript表达式,可以使用任何字符处理方法。例如:

type filename | findrepl "before (.*) after" /J "'before'+$1.substr(0,4).toUpperCase()+'after'"

您甚至可以通过逗号JScript运算符引入更复杂的JScript替换表达式,其中包含多个赋值(对辅助变量)。

答案 1 :(得分:1)

如果您还没有这样做,我强烈建议您从命令提示符执行以下命令:

获取特定于REPL.BAT的帮助:

repl /?

获取有关REPL.BAT使用的JScript正则表达式的帮助(在Web浏览器中打开MicroSoft文档)

repl /?regex

获取有关替换子匹配功能的帮助 - "变量"您正在寻找(在您的网络浏览器中打开MicroSoft文档)

repl /?replace

我在搜索正则表达式中用\s(单词边界)替换了前导\b。我还使用未转义的括号来捕获用户名和密码值,以便我可以在替换字符串中使用它们。 .*?匹配括号文字内的内容(非贪婪匹配)。一个化妆品更改是使用\q而不是\x22

type %filename% | repl "\bdriver\.find_element_by_id\(\qusername\q\)\.send_keys\((.*?)\)\s*driver\.find_element_by_id\(\qpassword\q\)\.send_keys\((.*?)\)" "login($1,$2)" MX >%filename%.new

<强>更新

根据OP的评论和Aacini的回答,我更新了REPL.BAT以接受J选项,将替换值指定为JScript表达式。

以下示例将用户名转换为大写:

type %filename% | repl "\bdriver\.find_element_by_id\(\qusername\q\)\.send_keys\((.*?)\)\s*driver\.find_element_by_id\(\qpassword\q\)\.send_keys\((.*?)\)" "'login('+$[1].toUpperCase()+','+$[2]+')'" MXJ >%filename%.new

有关详细信息和示例,请参阅http://www.dostips.com/forum/viewtopic.php?p=37855#p37855