<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script> </head> <body> <h1>Loop Read</h1> <p>检索文本文件中的行, 每次一行.</p> <pre class="Syntax"><span class="func">Loop Read</span> InputFile <span class="optional">, OutputFile</span></pre> <h2 id="Parameters">参数</h2> <dl> <dt>InputFile</dt> <dd> <p>类型: <a href="../Concepts.htm#strings">字符串</a></p> <p>需要在循环中读取其内容的文本文件的名称, 如果未指定绝对路径, 则假定在 <a href="../Variables.htm#WorkingDir">A_WorkingDir</a> 中. 文件的行结束符可以是回车和换行符(`r`n), 也可以只是换行符(`n), 或只是回车(`r).</p> </dd> <dt id="OutputFile">OutputFile</dt> <dd> <p>类型: <a href="../Concepts.htm#strings">字符串</a></p> <p>在循环期间保持打开的文件的名称, 如果未指定绝对路径, 则假定在 <a href="../Variables.htm#WorkingDir">A_WorkingDir</a> 中.</p> <p>在循环的主体内, 使用 <a href="FileAppend.htm">FileAppend</a> 函数, 不带 <em>Filename</em> 参数(即省略它) 来追加到这个特殊的文件. 以这种方式追加到一个文件比使用 2 个参数模式的 <a href="FileAppend.htm">FileAppend</a> 执行地更好, 因为每次操作时不需要关闭文件和再重新打开. 如果需要的话, 记得在文本后加入换行符(`n) 或回车符和换行符(`r`n).</p> <p>如果没有向文件写入任何内容, 文件就不会被打开. 如果循环执行零迭代或从未调用 <a href="FileAppend.htm">FileAppend</a>, 就会发生这种情况.</p> <p><strong>选项</strong>: 行末(EOL) 转换模式和输出文件编码取决于在 <a href="FileAppend.htm">FileAppend</a> 的首次调用中传递的选项(即省略 <em>Filename</em> 的首次调用). 随后的调用会忽略 <em>Options</em> 参数. 默认情况下不执行 EOL 转换; 也就是说, 除非存在 <code>"`n"</code> 选项, 否则换行符(`n) 将按原样写入.</p> <p><strong>标准输出(stdout)</strong>: 指定 <em>OutputFile</em> 为星号(*) 可以把 <a href="FileAppend.htm">FileAppend</a> 写入的任何文本发送到标准输出(stdout). 这些文本可以重定向到文件, 指向另一个 EXE 的管道或被<a href="_ErrorStdOut.htm">高级文本编辑器</a>捕获, 然而发送到标准输出的文本不会出现在运行它的命令提示符中. 这可以通过以下方法解决 1) 使用 <a href="../misc/Ahk2ExeDirectives.htm#ConsoleApp">Ahk2Exe ConsoleApp 指令</a>编译脚本, 或 2) 通过管道或重定向捕获脚本的输出. 有关详情, 请参阅 <a href="FileAppend.htm">FileAppend</a>.</p> </dd> </dl> <h2 id="Remarks">备注</h2> <p>当您想对包含在文本文件中的内容逐行进行操作时, 文件读取循环很有用. 在整个操作过程中, 文件是打开的, 以避免每次都要重新扫描以找到下一行.</p> <p id="LoopReadLine">内置变量 <strong>A_LoopReadLine</strong> 存在于任何文件读取循环中. 它包含当前行的内容, 不包括回车和标志行结束的换行符(`r`n). 如果一个内部的文件读取循环被一个外部的文件读取循环所包围, 那么最内部循环的文件行将优先.</p> <p>读取长度为 65,534 个字符的行. 如果行的长度超过了这个长度, 其剩余的字符将在下一个循环迭代时被读取.</p> <p><a href="StrSplit.htm">StrSplit</a> 或<a href="LoopParse.htm">解析循环</a>通常用于文件读取循环中, 以解析从 <em>InputFile</em> 中获取的每一行的内容. 例如, 如果 <em>InputFile</em> 的每一行都是一系列以 tab 分隔的字段, 那么这些字段可以像这个例子一样单独检索:</p> <pre>Loop read, "C:\Database Export.txt" { Loop parse, A_LoopReadLine, A_Tab { MsgBox "Field number " A_Index " is " A_LoopField "." } }</pre> <p>要加载整个文件内容到变量中, 请使用 <a href="FileRead.htm">FileRead</a>, 因为它比循环执行的更好(尤其对于大文件).</p> <p>要同时打开多个文件, 请使用 <a href="FileOpen.htm">FileOpen</a>.</p> <p>请参阅 <a href="Loop.htm">Loop</a> 了解关于<a href="Block.htm">区块</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a> 和 A_Index 变量(其存在于各种类型的循环中) 的相关信息.</p> <p>在不存在字节顺序标记时要控制如何解码文件, 请使用 <a href="FileEncoding.htm">FileEncoding</a>.</p> <p>循环的后面可以有一个可选的 <a href="Else.htm">Else</a> 语句, 如果输入文件是空的或者找不到的话, 就会执行这个语句. 如果指定了 <em>OutputFile</em>, <a href="#OutputFile">上面</a>描述的 <a href="FileAppend.htm">FileAppend</a> 的特殊模式也可以在 <em>Else</em> 语句的主体中使用. 如果没有 <em>Else</em> 语句, 如果找不到文件, 则抛出 <a href="../objects/Error.htm#OSError">OSError</a>.</p> <h2 id="Related">相关</h2> <p><a href="FileEncoding.htm">FileEncoding</a>, <a href="FileOpen.htm">FileOpen</a>/<a href="../objects/File.htm">File 对象</a>, <a href="FileRead.htm">FileRead</a>, <a href="FileAppend.htm">FileAppend</a>, <a href="Sort.htm">Sort</a>, <a href="Loop.htm">Loop</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, <a href="Block.htm">区块</a>, <a href="FileSetAttrib.htm">FileSetAttrib</a>, <a href="FileSetTime.htm">FileSetTime</a></p> <h2 id="Examples">示例</h2> <div class="ex" id="ExFileAppend"> <p><a class="ex_number" href="#ExFileAppend"></a> 只有首个文件中包含单词 FAMILY 的那些行才会写入第二个文件中. 取消注释首行可以覆盖而不是追加到任何现有的文件中.</p> <pre><em>;FileDelete "C:\Docs\Family Addresses.txt"</em> Loop read, "C:\Docs\Address List.txt", "C:\Docs\Family Addresses.txt" { if InStr(A_LoopReadLine, "family") FileAppend(A_LoopReadLine "`n") } else MsgBox "Address List.txt was completely empty or not found."</pre> </div> <div class="ex" id="ExLastLine"> <p><a class="ex_number" href="#ExLastLine"></a> 获取文本文件的最后一行.</p> <pre>Loop read, "C:\Log File.txt" last_line := A_LoopReadLine <em>; 当循环结束时, 这里会保持最后一行的内容.</em></pre> </div> <div class="ex" id="ExURL"> <p><a class="ex_number" href="#ExURL"></a> 尝试从文本或 HTML 文件中提取所有 FTP 和 HTTP URL.</p> <pre> SourceFile := FileSelect(3,, "Pick a text or HTML file to analyze.") if SourceFile = "" return <em>; 此时将退出.</em> SplitPath SourceFile,, &amp;SourceFilePath,, &amp;SourceFileNoExt DestFile := SourceFilePath "\" SourceFileNoExt " Extracted Links.txt" if FileExist(DestFile) { Result := MsgBox("Overwrite the existing links file? Press No to append to it.`n`nFILE: " DestFile,, 4) if Result = "Yes" FileDelete DestFile } LinkCount := 0 Loop read, SourceFile, DestFile { URLSearch(A_LoopReadLine) } MsgBox LinkCount ' links were found and written to "' DestFile '".' return URLSearch(URLSearchString) { <em>; 由于在一些 URL(网址) 中内嵌有其他的 URL, 所以用这种特殊的方法进行处理: ; 找到最左边的起始位置:</em> URLStart := 0 <em>; 设置起始默认值.</em> for URLPrefix in ["https://", "http://", "ftp://", "www."] { ThisPos := InStr(URLSearchString, URLPrefix) if !ThisPos <em>; 此前缀被取消资格.</em> continue if !URLStart URLStart := ThisPos else <em>; URLStart 里面有一个有效的位置, 所以要和 ThisPos 比较一下.</em> { if ThisPos &amp;&amp; ThisPos &lt; URLStart URLStart := ThisPos } } if !URLStart <em>; 在 URLSearchString 中不存在 URL.</em> return <em>; 否则, 提取该 URL:</em> URL := SubStr(URLSearchString, URLStart) <em>; 忽略开始/无效部分.</em> Loop parse, URL, " `t&lt;&gt;" <em>; 找到首个空格, tab 或尖括号(如果有).</em> { URL := A_LoopField break <em>; 即仅执行一次循环来获取首个 "片段".</em> } <em>; 如果上面的循环因为没有找到结尾字符而导致迭代次数为零, ; 那么 URL 变量的内容保持不变. ; 如果 URL 以双引号结束, 那么移除它. 暂时使用 StringReplace, 不过注意 ; 双引号似乎可以合法存在于 URL 中, 所以这样做 ; 可能破坏它们:</em> URLCleansed := StrReplace(URL, '"') FileAppend URLCleansed "`n" global LinkCount += 1 <em>; 看看当前行中是否含有其他 URL:</em> CharactersToOmit := StrLen(URL) CharactersToOmit += URLStart URLSearchString := SubStr(URLSearchString, CharactersToOmit) <em>; 到自身的递归调用:</em> URLSearch(URLSearchString) } </pre> </div> </body> </html>