起因
在C++ Primer中文第五版的第19页中,书上提到了一个文件重定向的功能:
由于我最近一直使用powershell进行编译和运行,在使用时发现这么写并不能正常运行,会提示如下信息:
“<”运算符是为将来使用而保留的。
+ CategoryInfo : ParserError: ( : ) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : RedirectionNotSupported
然后我在CMD中输入指令,发现可以正常运行,于是我打开了微软官方的Powershell网站开始寻找原因。
注意:以下所有的文件操作都是在同一个文件夹下操作,实际操作中既可以使用相对位置也可以使用绝对位置。
PowerShell管道
接下来我发现PowerShell有一个“管道”(pipe,其实一般应该叫“管线”比较多)的概念,即一个操作的通道或者说流水线。
在一个管道中,不同的操作步骤使用|
符号进行分隔,|
符号前的操作结果会被当作参数传入|
符号后的指令中。
例如下面一段内容,假设我们有"指令A"、“指令B”、"指令C"三个不同的指令,其中指令B和C都需要参数,我们需要从指令A中获得参数,依次传入指令B和指令C,最后由指令C来输出结果;在没有这个管道的情况下,我们可能需要先运行指令A,将运行结果保存下来,然后将这个结果传入指令B中再保存下来,最后把从指令B保存的结果传给指令C,这就多了两个缓存的数据,我们的指令可能写成这样:
$A=指令A (enter)
$C=指令B(enter)
$A(enter)
指令C(enter)
$B(enter)
但是在有了这个管线的情况下,我们就可以这样写:
指令A | 指令B | 指令C (enter)
是不是简单了非常多?
从文件传入
在有了管道操作以后,我们现在还需要一个从文件读取的指令,这在powershell指令中也非常容易找到:
从文件获取:Get-Content
这个Get-Content指令就是我们的目标,用它可以从txt或者其他文本文件中读取信息,标准格式如下:
Get-Content -Path inputPath
例如我们有一个文件,文件名是“input.txt”,我们只需要输入这个指令:
Get-Content input.txt
结果如下图所示
在官方说明中,完整形式还包括一个 -Path
指令,经测试,是可以省略的。
输出到文件
其实在C++ Primer中指令一共是三个组成部分:程序名、传入文件、输出文件,而在这之中,输入文件的指令> output
是可以使用的,但是事实上这并不符合PowerShell的管道规范(当然还是可以使用的,不过这里要说明管道的使用,只能委屈它一下了),于是我又找到了通用的输出文件的形式:
输出到文件
与输入文件指令一样,我们先上指令的标准形式:
Get-Process | Out-File -FilePath outputPath -Encoding ASCII
这就是一个非常标准的管道使用范例了,前面的Get-Process
是获得当前所有进程的指令,但是可以换成任意我们需要的指令,例如我们可以在这里使用一个Get-Content
指令,从一个文件中读取内容,并将它们输出到另一个文件中。
指令的最后是-Encoding ASCII
,由于默认保存是unicode(在我的系统中出来默认是UTF16),所以这里可以用于指定特定编码进行保存。
先进行一下测试 ,我们把"ABCDEFG"的字符串保存到output.txt文件中:
保存成功:
把指令连接起来
在有了这些基础知识,我们就可以完成完成的指令了,比如我这里有一个for.exe
文件,需要传入两个数,它会将这两个数之间的所有整数从小到大输出,我们还是从input.txt输入,从output.txt输出。
input.txt文件内容如下:
10 20
output.txt文件是空白。
输入指令
PS> Get-Content input.txt | .\for | Out-File output.txt
成功得到结果:
总结
相对CMD的指令而言,powershell的管道指令看起来确实要麻烦一些,但是在实际运行中会发现这一套运行逻辑更加容易使用,它可以方便地组合各种各样的指令来实现想要的功能,而CMD中对不同的指令必须使用它所定义的参数。