如何使用Windows命令行环境查找和替换文件中的文本?

How can you find and replace text in a file using the Windows command-line environment?

我正在使用Windows命令行环境编写批处理文件脚本,并希望用另一个(例如"bar")更改文件中某些文本的每次出现(例如"foo")。最简单的方法是什么?有内置功能吗?


这里的许多答案帮助我找到了正确的方向,但是没有一个适合我,所以我发布了我的解决方案。

我有Windows7,它内置了PowerShell。下面是我用来查找/替换文件中所有文本实例的脚本:

1
powershell -Command"(gc myFile.txt) -replace 'foo', 'bar' | Out-File myFile.txt"

解释它:

  • powershell启动PowerShell.exe,它包含在Windows7中。
  • -Command"..."是PowerShell.exe的命令行arg,包含要运行的命令
  • (gc myFile.txt)读取myFile.txt的内容(gcGet-Content命令的缩写)
  • -replace 'foo', 'bar'简单地运行replace命令,用bar替换foo
  • | Out-File myFile.txt将输出传输到文件myFile.txt中。

powershell.exe应该已经是path语句的一部分,但如果不是,则可以添加它。它在我的机器上的位置是C:\WINDOWS\system32\WindowsPowerShell\v1.0


如果您使用的是支持.NET 2.0的Windows版本,我将替换您的shell。PowerShell通过命令行为您提供.NET的全部功能。还有许多内置的命令。下面的例子将解决您的问题。我使用的是命令的全名,有较短的别名,但这给了你一些谷歌的东西。

1
(Get-Content test.txt) | ForEach-Object { $_ -replace"foo","bar" } | Set-Content test2.txt


刚刚使用了f a r t("F ind a nd r eplace t ext"命令行实用程序):优秀的小免费软件,用于在一大组文件中替换文本。

安装文件在sourceforge上。

使用实例:

1
fart.exe -p -r -c -- C:\tools\perl-5.8.9\* @@APP_DIR@@ C:\tools

将在这个Perl发行版的文件中预览要递归执行的替换。

唯一的问题是,"放屁"网站的图标并不雅致、精致或优雅;)

更新2017年(7年后)Jagb在2011年Mikail Tun的文章"放屁的简单方式-查找和替换文本"的评论中指出。


替换-使用字符串替换替换子字符串描述:要用另一个字符串替换子字符串,请使用字符串替换功能。这里显示的示例将所有出现的"teh"拼写错误替换为字符串变量str中的"the"。

1
2
3
4
set str=teh cat in teh hat
echo.%str%
set str=%str:teh=the%
echo.%str%

脚本输出:

1
2
teh cat in teh hat
the cat in the hat

参考:http://www.dostips.com/dttipstringmanipulation.php snippets.replace


创建文件replace.vbs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Const ForReading = 1    
Const ForWriting = 2

strFileName = Wscript.Arguments(0)
strOldText = Wscript.Arguments(1)
strNewText = Wscript.Arguments(2)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll
objFile.Close

strNewText = Replace(strText, strOldText, strNewText)
Set objFile = objFSO.OpenTextFile(strFileName, ForWriting)
objFile.Write strNewText  'WriteLine adds extra CR/LF
objFile.Close

要使用此修订脚本(我们将称之为replace.vbs),只需在命令提示下键入与此类似的命令:

cscript replace.vbs"C:\Scripts\Text.txt""Jim""James"


dostips.com上的BatchSubstitute.bat是使用纯批处理文件进行搜索和替换的示例。

它使用了FORFINDCALL SET的组合。

包含"&<>]|^中字符的行可能被错误地处理。


注意-请务必查看此答案末尾的更新,以获取取代repl.bat的superior jrepl.bat的链接。jrepl.bat 7.0及更高版本本机支持通过/UTF选项的unicode(utf-16le),以及通过ado的任何其他字符集,包括utf-8!!!!!

我编写了一个名为repl.bat的小型混合JScript/batch实用程序,它非常方便通过命令行或批处理文件修改ASCII(或扩展的ASCII)文件。纯本机脚本不需要安装任何可执行的第三方,它可以在XP以后的任何现代Windows版本上工作。它也非常快,特别是与纯批处理溶液相比。

repl.bat只读取stdin,执行jscript regex搜索和替换,并将结果写入stdout。

下面是一个简单的例子,说明如何在test.txt中将foo替换为bar,假设repl.bat在当前文件夹中,或者更好地说,在路径中的某个位置:

1
2
type test.txt|repl"foo""bar">test.txt.new
move /y test.txt.new test.txt

JScriptRegex功能使其非常强大,尤其是替换文本引用从搜索文本捕获的子字符串的能力。

我在实用程序中加入了许多选项,使它非常强大。例如,结合MX选项可以修改二进制文件!M多行选项允许跨多行搜索。X扩展替换模式选项提供转义序列,允许在替换文本中包含任何二进制值。

整个实用程序可以作为纯JScript编写,但是混合批处理文件消除了每次使用该实用程序时显式指定CScript的需要。

这是repl.bat脚本。完整的文档嵌入在脚本中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::************ Documentation ***********
::REPL.BAT version 6.2
:::
:::REPL  Search  Replace  [Options  [SourceVar]]
:::REPL  /?[REGEX|REPLACE]
:::REPL  /V
:::
:::  Performs a global regular expression search and replace operation on
:::  each line of input from stdin and prints the result to stdout.
:::
:::  Each parameter may be optionally enclosed by double quotes. The double
:::  quotes are not considered part of the argument. The quotes are required
:::  if the parameter contains a batch token delimiter like space, tab, comma,
:::  semicolon. The quotes should also be used if the argument contains a
:::  batch special character like &, |, etc. so that the special character
:::  does not need to be escaped with ^.
:::
:::  If called with a single argument of /?, then prints help documentation
:::  to stdout. If a single argument of /?REGEX, then opens up Microsoft's
:::  JScript regular expression documentation within your browser. If a single
:::  argument of /?REPLACE, then opens up Microsoft's JScript REPLACE
:::  documentation within your browser.
:::
:::  If called with a single argument of /V, case insensitive, then prints
:::  the version of REPL.BAT.
:::
:::  Search  - By default, this is a case sensitive JScript (ECMA) regular
:::            expression expressed as a string.
:::
:::            JScript regex syntax documentation is available at
:::            http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
:::  Replace - By default, this is the string to be used as a replacement for
:::            each found search expression. Full support is provided for
:::            substituion patterns available to the JScript replace method.
:::
:::            For example, $& represents the portion of the source that matched
:::            the entire search pattern, $1 represents the first captured
:::            submatch, $2 the second captured submatch, etc. A $ literal
:::            can be escaped as $$.
:::
:::            An empty replacement string must be represented as"".
:::
:::            Replace substitution pattern syntax is fully documented at
:::            http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
:::  Options - An optional string of characters used to alter the behavior
:::            of REPL. The option characters are case insensitive, and may
:::            appear in any order.
:::
:::            A - Only print altered lines. Unaltered lines are discarded.
:::                If the S options is present, then prints the result only if
:::                there was a change anywhere in the string. The A option is
:::                incompatible with the M option unless the S option is present.
:::
:::            B - The Search must match the beginning of a line.
:::                Mostly used with literal searches.
:::
:::            E - The Search must match the end of a line.
:::                Mostly used with literal searches.
:::
:::            I - Makes the search case-insensitive.
:::
:::            J - The Replace argument represents a JScript expression.
:::                The expression may access an array like arguments object
:::                named $. However, $ is not a true array object.
:::
:::                The $.length property contains the total number of arguments
:::                available. The $.length value is equal to n+3, where n is the
:::                number of capturing left parentheses within the Search string.
:::
:::                $[0] is the substring that matched the Search,
:::                $[1] through $[n] are the captured submatch strings,
:::                $[n+1] is the offset where the match occurred, and
:::                $[n+2] is the original source string.
:::
:::                Arguments $[0] through $[10] may be abbreviated as
:::                $1 through $10. Argument $[11] and above must use the square
:::                bracket notation.
:::
:::            L - The Search is treated as a string literal instead of a
:::                regular expression. Also, all $ found in the Replace string
:::                are treated as $ literals.
:::
:::            M - Multi-line mode. The entire contents of stdin is read and
:::                processed in one pass instead of line by line, thus enabling
:::                search for
. This also enables preservation of the original
:::                line terminators. If the M option is not present, then every
:::                printed line is terminated with carriage return and line feed.
:::                The M option is incompatible with the A option unless the S
:::                option is also present.
:::
:::                Note: If working with binary data containing NULL bytes,
:::                      then the M option must be used.
:::
:::            S - The source is read from an environment variable instead of
:::                from stdin. The name of the source environment variable is
:::                specified in the next argument after the option string. Without
:::                the M option, ^ anchors the beginning of the string, and $ the
:::                end of the string. With the M option, ^ anchors the beginning
:::                of a line, and $ the end of a line.
:::
:::            V - Search and Replace represent the name of environment
:::                variables that contain the respective values. An undefined
:::                variable is treated as an empty string.
:::
:::            X - Enables extended substitution pattern syntax with support
:::                for the following escape sequences within the Replace string:
:::
:::                \\     -  Backslash
:::                \b     -  Backspace
:::                \f     -  Formfeed
:::                
     -  Newline
:::                \q     -  Quote
:::                
     -  Carriage Return
:::                \t     -  Horizontal Tab
:::                \v     -  Vertical Tab
:::                \xnn   -  Extended ASCII byte code expressed as 2 hex digits
:::                \unnnn -  Unicode character expressed as 4 hex digits
:::
:::                Also enables the \q escape sequence for the Search string.
:::                The other escape sequences are already standard for a regular
:::                expression Search string.
:::
:::                Also modifies the behavior of \xnn in the Search string to work
:::                properly with extended ASCII byte codes.
:::
:::                Extended escape sequences are supported even when the L option
:::                is used. Both Search and Replace support all of the extended
:::                escape sequences if both the X and L opions are combined.
:::
:::  Return Codes:  0 = At least one change was made
:::                     or the /? or /V option was used
:::
:::                 1 = No change was made
:::
:::                 2 = Invalid call syntax or incompatible options
:::
:::                 3 = JScript runtime error, typically due to invalid regex
:::
::: REPL.BAT was written by Dave Benham, with assistance from DosTips user Aacini
::: to get \xnn to work properly with extended ASCII byte codes. Also assistance
::: from DosTips user penpen diagnosing issues reading NULL bytes, along with a
::: workaround. REPL.BAT was originally posted at:
::: http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
:::

::************ Batch portion ***********
@echo off
if .%2 equ . (
  if"%~1" equ"/?" (
    <"%~f0" cscript //E:JScript //nologo"%~f0""^:::""" a
    exit /b 0
  ) else if /i"%~1" equ"/?regex" (
    explorer"http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx"
    exit /b 0
  ) else if /i"%~1" equ"/?replace" (
    explorer"http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx"
    exit /b 0
  ) else if /i"%~1" equ"/V" (
    <"%~f0" cscript //E:JScript //nologo"%~f0""^::(REPL\.BAT version)""$1" a
    exit /b 0
  ) else (
    call :err"Insufficient arguments"
    exit /b 2
  )
)
echo(%~3|findstr /i"[^SMILEBVXAJ]">nul && (
  call :err"Invalid option(s)"
  exit /b 2
)
echo(%~3|findstr /i"M"|findstr /i"A"|findstr /vi"S">nul && (
  call :err"Incompatible options"
  exit /b 2
)
cscript //E:JScript //nologo"%~f0" %*
exit /b %errorlevel%

:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b

************* JScript portion **********/
var rtn=1;
try {
  var env=WScript.CreateObject("WScript.Shell").Environment("Process");
  var args=WScript.Arguments;
  var search=args.Item(0);
  var replace=args.Item(1);
  var options="g";
  if (args.length>2) options+=args.Item(2).toLowerCase();
  var multi=(options.indexOf("m")>=0);
  var alterations=(options.indexOf("a")>=0);
  if (alterations) options=options.replace(/a/g,"");
  var srcVar=(options.indexOf("s")>=0);
  if (srcVar) options=options.replace(/s/g,"");
  var jexpr=(options.indexOf("j")>=0);
  if (jexpr) options=options.replace(/j/g,"");
  if (options.indexOf("v")>=0) {
    options=options.replace(/v/g,"");
    search=env(search);
    replace=env(replace);
  }
  if (options.indexOf("x")>=0) {
    options=options.replace(/x/g,"");
    if (!jexpr) {
      replace=replace.replace(/\\\\/g,"\\B");
      replace=replace.replace(/\\q/g,""");
      replace=replace.replace(/\\x80/g,"\\u20AC");
      replace=replace.replace(/\\x82/g,"\\u201A");
      replace=replace.replace(/\\x83/g,"\\u0192");
      replace=replace.replace(/\\x84/g,"\\u201E");
      replace=replace.replace(/\\x85/g,"\\u2026");
      replace=replace.replace(/\\x86/g,"\\u2020");
      replace=replace.replace(/\\x87/g,"\\u2021");
      replace=replace.replace(/\\x88/g,"\\u02C6");
      replace=replace.replace(/\\x89/g,"\\u2030");
      replace=replace.replace(/\\x8[aA]/g,"\\u0160");
      replace=replace.replace(/\\x8[bB]/g,"\\u2039");
      replace=replace.replace(/\\x8[cC]/g,"\\u0152");
      replace=replace.replace(/\\x8[eE]/g,"\\u017D");
      replace=replace.replace(/\\x91/g,"\\u2018");
      replace=replace.replace(/\\x92/g,"\\u2019");
      replace=replace.replace(/\\x93/g,"\\u201C");
      replace=replace.replace(/\\x94/g,"\\u201D");
      replace=replace.replace(/\\x95/g,"\\u2022");
      replace=replace.replace(/\\x96/g,"\\u2013");
      replace=replace.replace(/\\x97/g,"\\u2014");
      replace=replace.replace(/\\x98/g,"\\u02DC");
      replace=replace.replace(/\\x99/g,"\\u2122");
      replace=replace.replace(/\\x9[aA]/g,"\\u0161");
      replace=replace.replace(/\\x9[bB]/g,"\\u203A");
      replace=replace.replace(/\\x9[cC]/g,"\\u0153");
      replace=replace.replace(/\\x9[dD]/g,"\\u009D");
      replace=replace.replace(/\\x9[eE]/g,"\\u017E");
      replace=replace.replace(/\\x9[fF]/g,"\\u0178");
      replace=replace.replace(/\\b/g,"\b");
      replace=replace.replace(/\\f/g,"\f");
      replace=replace.replace(/\
/g,"
");
      replace=replace.replace(/\
/g,"
");
      replace=replace.replace(/\\t/g,"\t");
      replace=replace.replace(/\\v/g,"\v");
      replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
        function($0,$1,$2){
          return String.fromCharCode(parseInt("0x"+$0.substring(2)));
        }
      );
      replace=replace.replace(/\\B/g,"\");
    }
    search=search.replace(/\\\\/g,"\\B");
    search=search.replace(/\\q/g,""");
    search=search.replace(/\\x80/g,"\\u20AC");
    search=search.replace(/\\x82/g,"\\u201A");
    search=search.replace(/\\x83/g,"\\u0192");
    search=search.replace(/\\x84/g,"\\u201E");
    search=search.replace(/\\x85/g,"\\u2026");
    search=search.replace(/\\x86/g,"\\u2020");
    search=search.replace(/\\x87/g,"\\u2021");
    search=search.replace(/\\x88/g,"\\u02C6");
    search=search.replace(/\\x89/g,"\\u2030");
    search=search.replace(/\\x8[aA]/g,"\\u0160");
    search=search.replace(/\\x8[bB]/g,"\\u2039");
    search=search.replace(/\\x8[cC]/g,"\\u0152");
    search=search.replace(/\\x8[eE]/g,"\\u017D");
    search=search.replace(/\\x91/g,"\\u2018");
    search=search.replace(/\\x92/g,"\\u2019");
    search=search.replace(/\\x93/g,"\\u201C");
    search=search.replace(/\\x94/g,"\\u201D");
    search=search.replace(/\\x95/g,"\\u2022");
    search=search.replace(/\\x96/g,"\\u2013");
    search=search.replace(/\\x97/g,"\\u2014");
    search=search.replace(/\\x98/g,"\\u02DC");
    search=search.replace(/\\x99/g,"\\u2122");
    search=search.replace(/\\x9[aA]/g,"\\u0161");
    search=search.replace(/\\x9[bB]/g,"\\u203A");
    search=search.replace(/\\x9[cC]/g,"\\u0153");
    search=search.replace(/\\x9[dD]/g,"\\u009D");
    search=search.replace(/\\x9[eE]/g,"\\u017E");
    search=search.replace(/\\x9[fF]/g,"\\u0178");
    if (options.indexOf("l")>=0) {
      search=search.replace(/\\b/g,"\b");
      search=search.replace(/\\f/g,"\f");
      search=search.replace(/\
/g,"
");
      search=search.replace(/\
/g,"
");
      search=search.replace(/\\t/g,"\t");
      search=search.replace(/\\v/g,"\v");
      search=search.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
        function($0,$1,$2){
          return String.fromCharCode(parseInt("0x"+$0.substring(2)));
        }
      );
      search=search.replace(/\\B/g,"\");
    } else search=search.replace(/\\B/g,"\\\");
  }
  if (options.indexOf("l")>=0) {
    options=options.replace(/l/g,"");
    search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
    if (!jexpr) replace=replace.replace(/\$/g,"$$$$");
  }
  if (options.indexOf("b")>=0) {
    options=options.replace(/b/g,"");
    search="^"+search
  }
  if (options.indexOf("e")>=0) {
    options=options.replace(/e/g,"");
    search=search+"$"
  }
  var search=new RegExp(search,options);
  var str1, str2;

  if (srcVar) {
    str1=env(args.Item(3));
    str2=str1.replace(search,jexpr?replFunc:replace);
    if (!alterations || str1!=str2) if (multi) {
      WScript.Stdout.Write(str2);
    } else {
      WScript.Stdout.WriteLine(str2);
    }
    if (str1!=str2) rtn=0;
  } else if (multi){
    var buf=1024;
    str1="";
    while (!WScript.StdIn.AtEndOfStream) {
      str1+=WScript.StdIn.Read(buf);
      buf*=2
    }
    str2=str1.replace(search,jexpr?replFunc:replace);
    WScript.Stdout.Write(str2);
    if (str1!=str2) rtn=0;
  } else {
    while (!WScript.StdIn.AtEndOfStream) {
      str1=WScript.StdIn.ReadLine();
      str2=str1.replace(search,jexpr?replFunc:replace);
      if (!alterations || str1!=str2) WScript.Stdout.WriteLine(str2);
      if (str1!=str2) rtn=0;
    }
  }
} catch(e) {
  WScript.Stderr.WriteLine("JScript runtime error:"+e.message);
  rtn=3;
}
WScript.Quit(rtn);

function replFunc($0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10) {
  var $=arguments;
  return(eval(replace));
}

< BR>重要更新

我已经停止了repl.bat的开发,并将其替换为jrepl.bat。这个新的实用程序具有repl.bat的所有相同功能,另外还有:

  • 通过本机CScript Unicode功能支持Unicode UTF-16LE,通过ADO支持任何其他字符集(包括UTF-8)。
  • 直接从/写入文件:不需要管道、重定向或移动命令。
  • 合并用户提供的JScript
  • 与unix tr类似的翻译工具,只支持regex搜索和jscript替换
  • 放弃不匹配的文本
  • 在输出行前面加上行号
  • 还有更多…

和往常一样,完整的文档嵌入到脚本中。

最初的琐碎解决方案现在更简单了:

1
jrepl"foo""bar" /f test.txt /o -

当前版本的jrepl.bat在dostips上提供。阅读线程中随后的所有文章,以查看用法示例和开发历史。


使用FNR

使用fnr实用程序。它比fart有一些优势:

  • 正则表达式
  • 可选的图形用户界面。有一个"生成命令行按钮"来创建要放入批处理文件的命令行文本。
  • 多行模式:GUI允许您轻松地使用多行模式。在"放屁"中,你必须手动避开换行符。
  • 允许您选择文本文件编码。还有一个自动检测选项。

在此处下载fnr:http://findandsreplace.io/?Z= COMPUTEX

使用实例:fnr --cl --dir"" --fileMask"hibernate.*" --useRegEx --find"find_str_expression" --replace"replace_string"


我认为没有一种方法可以使用任何内置命令。我建议您下载类似于gnuwin32或unxutils的内容,并使用sed命令(或仅下载sed命令):

1
sed -c s/FOO/BAR/g filename


我知道我参加晚会迟到了。

就个人而言,我喜欢以下解决方案:-http://www.dostips.com/dttipstringmanipulation.php snippets.replace

此外,我们还广泛使用重复数据消除功能,帮助我们每天通过SMTP发送大约500封电子邮件,从:-https://groups.google.com/forum/!主题/alt.msdos.batch.nt/sj8iuhmoq6o

它们都是本地工作的,不需要额外的工具或实用程序。

替代品:

1
2
3
4
5
6
7
8
DEL New.txt
setLocal EnableDelayedExpansion
For /f"tokens=* delims=" %%a in (OLD.txt) do (
Set str=%%a
set str=!str:FOO=BAR!
echo !str!>>New.txt
)
ENDLOCAL

除尘器(注意ABA编号使用-9):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
REM DE-DUPLICATE THE Mapping.txt FILE
REM THE DE-DUPLICATED FILE IS STORED AS new.txt

set MapFile=Mapping.txt
set ReplaceFile=New.txt

del %ReplaceFile%
::DelDupeText.bat
rem https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/sj8IUhMOq6o
setLocal EnableDelayedExpansion
for /f"tokens=1,2 delims=," %%a in (%MapFile%) do (
set str=%%a
rem Ref: http://www.dostips.com/DtTipsStringManipulation.php#Snippets.RightString
set str=!str:~-9!
set str2=%%a
set str3=%%a,%%b

find /i ^"!str!^" %MapFile%
find /i ^"!str!^" %ReplaceFile%
if errorlevel 1 echo !str3!>>%ReplaceFile%
)
ENDLOCAL

谢谢!


在Windows上使用Git时,只需启动git-bash使用sed。或者,在使用Windows10时,启动"bash on ubuntu on windows"(从Linux子系统)并使用sed

它是一个流编辑器,但可以使用以下命令直接编辑文件:

1
sed -i -e 's/foo/bar/g' filename
  • -i选项用于对文件名进行就地编辑。
  • -e选项表示要运行的命令。
    • s用于将找到的表达式"foo"替换为"bar",g用于替换任何找到的匹配项。

艾伦笔记:

如果要仅替换Git存储库的版本化文件中的字符串,则可能需要使用:

git ls-files | xargs sed -i -e 's/foo/bar/g'

创造奇迹。


我在这里讨论了一些现有的答案,并且更喜欢我改进的解决方案…

1
type test.txt | powershell -Command"$input | ForEach-Object { $_ -replace "foo", "bar" }"

或者,如果要再次将输出保存到文件中…

1
type test.txt | powershell -Command"$input | ForEach-Object { $_ -replace "foo", "bar" }"> outputFile.txt

这样做的好处是您可以从任何程序输入输出。也将研究使用正则表达式。但无法解决如何将其转换为BAT文件以便于使用…:


我用过Perl,效果非常好。

1
perl -pi.orig -e"s/<textToReplace>/<textToReplaceWith>/g;" <fileName>

.orig是它将附加到原始文件的扩展名。

对于许多匹配的文件,如*.html

1
for %x in (<filePattern>) do perl -pi.orig -e"s/<textToReplace>/<textToReplaceWith>/g;" %x


用替换器.bat

1)使用e?选项来评估特殊字符序列,如

和unicode序列。在这种情况下,将替换引用的"Foo""Bar"

1
call replacer.bat"e?C:\content.txt""\u0022Foo\u0022""\u0022Bar\u0022"

2)如果没有引用foobar,则直接替换。

1
call replacer.bat"C:\content.txt""Foo""Bar"


这里有一个解决方案,我发现它适用于Win XP。在运行的批处理文件中,我包含以下内容:

1
2
3
4
5
6
7
8
9
10
11
set value=new_value

:: Setup initial configuration
:: I use && as the delimiter in the file because it should not exist, thereby giving me the whole line
::
echo --> Setting configuration and properties.
for /f"tokens=* delims=&&" %%a in (config\config.txt) do (
  call replace.bat"%%a" _KEY_ %value% config\temp.txt
)
del config\config.txt
rename config\temp.txt config.txt

replace.bat文件如下。我没有找到将该函数包含在同一批文件中的方法,因为%%a变量似乎总是给出for循环中的最后一个值。

replace.bat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@echo off

:: This ensures the parameters are resolved prior to the internal variable
::
SetLocal EnableDelayedExpansion

:: Replaces Key Variables
::
:: Parameters:
:: %1  = Line to search for replacement
:: %2  = Key to replace
:: %3  = Value to replace key with
:: %4  = File in which to write the replacement
::

:: Read in line without the surrounding double quotes (use ~)
::
set line=%~1

:: Write line to specified file, replacing key (%2) with value (%3)
::
echo !line:%2=%3! >> %4

:: Restore delayed expansion
::
EndLocal


看看是否有任何类似于sed的实用程序用于cmd.exe,它要求在Windows下使用sed等效工具,也应该应用于这个问题。执行摘要:

  • 它可以在批处理文件中完成,但不漂亮
  • 如果您可以随意安装或复制一个exe文件,那么很多可用的第三方可执行文件都可以为您执行。
  • 可以使用vbscript或类似工具来完成,如果您需要一些能够在Windows框上运行而不需要修改的东西等。

栈溢出成员dbenhamaacini使用windows中的native built-in jscript编写了两个提供search and replace功能的批处理文件。

与纯批脚本相比,它们既有robustvery swift with large files,也有simpler,用于文本的基本替换。它们都有Windows regular expression模式匹配。

  • 这个sed-like助手批处理文件称为repl.bat(由dbenham编写)。

    使用L字面值开关的示例:

    1
    2
    3
    echo This is FOO here|repl"FOO""BAR" L
    echo and with a file:
    type"file.txt" |repl"FOO""BAR" L >"newfile.txt"
  • 这个grep-like助手批处理文件称为findrepl.bat(由aacini编写)。

    激活正则表达式的示例:

    1
    2
    3
    echo This is FOO here|findrepl"FOO""BAR"
    echo and with a file:
    type"file.txt" |findrepl"FOO""BAR">"newfile.txt"
  • 两者都成为强大的系统范围实用程序when placed in a folder that is on the path,或者可以与批处理文件一起在同一个文件夹中使用,或者从命令提示符中使用。

    它们都有case-insensitive开关和许多其他功能。


    可能有点晚了,但我经常寻找类似的东西,因为我不想经历软件批准的痛苦。

    但是,您通常以各种形式使用for语句。有人创建了一个有用的批处理文件来进行搜索和替换。看看这里。理解提供的批处理文件的局限性是很重要的。因此,我不复制此答案中的源代码。


    刚刚遇到了一个类似的问题——"在文件中搜索和替换文本",但是除了文件名和搜索/重新封装都需要使用regex。因为我不熟悉PowerShell,并且想保存搜索以便以后使用,所以我需要一些更"用户友好"的东西(如果它有GUI,则更可取)。

    所以,在谷歌搜索的时候,我发现了一个很好的工具——远(找到并替换)(不是放屁)。

    这个小程序有很好的图形用户界面,支持regex在文件名和文件中进行搜索。唯一的缺点是,如果要保存设置,必须以管理员身份运行程序(至少在Win7上)。


    强力壳命令就像一个魔咒

    1
    2
    3
    (
    test.txt | ForEach-Object { $_ -replace"foo","bar" } | Set-Content test2.txt
    )

    @Rachel给出了一个很好的答案,但这里有一个变体,用于将内容读取到PowerShell $data变量。在写入输出文件之前,您可以轻松地多次操作内容。另请参见.bat批处理文件中如何给出多行值。

    1
    2
    3
    4
    5
    6
    7
    8
    @REM ASCII=7bit ascii(no bom), UTF8=with bom marker
    set cmd=^
      $old = '\$Param1\$'; ^
      $new = 'Value1'; ^
      [string[]]$data = Get-Content 'datafile.txt'; ^
      $data = $data -replace $old, $new; ^
      out-file -InputObject $data -encoding UTF8 -filepath 'datafile.txt';
    powershell -NoLogo -Noninteractive -InputFormat none -Command"%cmd%"

    这是一件批量脚本编写不太好的事情。

    链接到的脚本morechili可以用于某些文件,但不幸的是,它会阻塞包含管道和符号等字符的文件。

    vbscript是用于此任务的更好的内置工具。有关示例,请参阅本文:http://www.microsoft.com/technet/scriptcenter/resources/qanda/feb05/hey0208.mspx


    在.bat中使用PowerShell-用于Windows 7+

    编码utf8是可选的,适用于网站

    1
    2
    3
    4
    5
    @echo off
    set ffile='myfile.txt'
    set fold='FOO'
    set fnew='BAR'
    powershell -Command"(gc %ffile%) -replace %fold%, %fnew% | Out-File %ffile% -encoding utf8"

    我更喜欢使用GNU实用程序中的sed来创建win32,需要注意以下几点

    • single quote '' won't work in windows, use "" instead
    • sed -i won't work in windows, it will need file swapping

    因此,在Windows中查找和替换文件中文本的sed的工作代码如下

    1
    sed -e"s/foo/bar/g" test.txt > tmp.txt && mv tmp.txt test.txt


    也可以在https://zoomicon.github.io/tranxform/上看到replace和replaceFilter工具(包含源代码)。第二个是过滤器。

    替换文件中字符串的工具位于vbscript中(需要在旧Windows版本中运行Windows脚本宿主[wsh])。

    除非使用最新的delphi(或freepascal/lazarus)重新编译,否则筛选器可能无法使用unicode。


    下载cygwin(免费)并在Windows命令行使用类似Unix的命令。

    您的最佳选择:SED


    在VisualC++环境下编码时,我曾多次遇到这个问题。如果有,可以使用Visual Studio查找和替换实用程序。它允许您选择一个文件夹,并用所需的任何其他文本替换该文件夹中任何文件的内容。

    在Visual Studio下:编辑->查找和替换在打开的对话框中,选择文件夹并填写"查找内容"和"替换为"框。希望这会有所帮助。