如何从文本文件

时间:2015-08-30 21:10:14

标签: windows powershell batch-file

我的文本文件包含一行注释,所有注释都是" //"。两个正斜杠和一个空格。这些可能占据整条线,也可能只占线的最后一部分。每条评论都不会延伸到它所在的界限之外。所以没有/ * * /类型注释跨越多行。

简单来说,所有评论都以" // space"开头。在线的任何地方。任何以" // space"开头的东西应该删除,并删除该行上的尾随空格。领先的空间应该留下来应删除任何空白行。

示例文件:

// This is a comment
x = 1 // This is also a comment after the double slash
x = 2

x = 3  // The above is a blank line
          // Comment on this record but nothing precedes it, so should be deleted.
   y = 4 // A line with leading spaces that should be kept.
z = "//path"; // The first double slashes are not a comment since the space is missing after the "//"
// Last comment line.

结果文件(没有尾随空格,但保留前导空格。:

x = 1
x = 2
x = 3
   y = 4
z = "//path";

我可以使用gc file.txt |删除空白行Where-Object {$ _ -ne''}>的Result.txt。但是,我只是在阅读" //"的一行的开头部分时遇到了麻烦。评论部分。

我也尝试过findtr但是还没找到如何读取每一行到#34; //"然后修剪空格。

我可以编写一个脚本程序来遍历文件并执行此操作,但似乎应该有一种方法可以使用简单的一行或两行PowerShell或bat文件命令来完成它。

在保留文件的未注释内容的同时删除这些注释的最简单方法(最短的代码量)是什么?

3 个答案:

答案 0 :(得分:2)

因为你似乎等同于" easy"使用"短",这是一个相当简单的解决方案:

gc .\samplefile.txt|%{$_-replace"(.*)(// .*)",'$1'}|?{$_}

如果它真的对你很重要: - )

更冗长的版本(仍在使用正则表达式):

Get-Content .\samplefile.txt | Where-Object {
    -not ([String]::IsNullOrEmpty($_.Trim()) -or $_-match"^\s*// ")
} |ForEach-Object { $_ -replace "(.*)(// .*)",'$1' }

话虽如此,我会(亲自)寻求更详细,更易于阅读/维护的解决方案:

要删除//之后的所有内容,最简单的方法是找到//第一次出现String.IndexOf(),然后使用String.Substring()抓住第一部分:

PS C:\> $CommentedString = "Content // this is a comment"
PS C:\> $CommentIndex    = $CommentedString.IndexOf('// ')
PS C:\> $CommentedString.Substring(0,$CommentIndex)
Content 

对于缩进注释,您还可以使用String.Trim()从字符串的开头和结尾删除空格:

PS C:\> "    // Indented comment" -match '^//'
True

您可以使用ForEach-Object cmdlet浏览每一行并应用上述内容:

function Remove-Comments {
    param(
        [string]$Path,
        [string]$OutFile
    )

    # Read file, remove comments and blank lines
    $CleanLines = Get-Content $Path |ForEach-Object {

        $Line = $_

        # Trim() removes whitespace from both ends of string
        $TrimmedLine = $Line.Trim()

        # Check if what's left is either nothing or a comment
        if([string]::IsNullOrEmpty($TrimmedLine) -or $TrimmedLine -match "^// ") {
            # if so, return nothing (inside foreach-object "return" acts like "coninue")
            return 
        }

        # See if non-empty line contains comment
        $CommentIndex = $Line.IndexOf("// ")

        if($CommentIndex -ge 0) {
            # if so, remove the comment
            $Line = $Line.Substring(0,$CommentIndex)
        }

        # return $Line to $CleanLines
        return $Line
    }

    if($OutFile -and (Test-Path $OutFile)){
        [System.IO.File]::WriteAllLines($OutFile, $CleanLines)
    } else {
        # No OutFile was specified, write lines to pipeline
        Write-Output $CleanLines
    }
}

适用于您的样本:

PS C:\> Remove-Comments D:\samplefile.txt
x = 1
x = 2
x = 3

答案 1 :(得分:1)

与许多文本处理问题一样,使用JREPL.BAT - a powerful regex text processing utility for the Windows command line有一个简单的解决方案。它是纯脚本(混合JScript /批处理),可以在XP之后的任何Windows机器上本机运行。完整的文档嵌入在脚本中。

jrepl "^(.*?)\s*// " "$1!=''?$1:false" /jmatch /f test.txt /o out.txt

您可以通过将-指定为输出文件来覆盖原始文件:

jrepl "^(.*?)\s*// " "$1!=''?$1:false" /jmatch /f test.txt /o -

我已经过测试,它会提供您正在寻找的确切输出。

如果您将命令放在批处理脚本中,则必须使用call jrepl

答案 2 :(得分:1)

下面的批处理文件做你想要的。对不起,但没有一个简单的短代码"这样做...

@echo off
setlocal EnableDelayedExpansion

rem Set the maximum number of trailing spaces as a power_of_2-1 value. For example, for 15 spaces:
set spcPow2=4

set "spaces= "
for /L %%i in (1,1,%spcPow2%) do set "spaces=!spaces!!spaces!"
set /A spcPow2-=1

rem Process all lines, excepting empty ones and lines that start with "/"
setlocal DisableDelayedExpansion
for /F "eol=/ delims=" %%a in (test.txt) do (
   set "line=%%a"

   rem Split line at "// " and get the first part
   setlocal EnableDelayedExpansion
   for /F "delims=¡" %%b in ("!line:// =¡!") do (
      endlocal
      set "line=%%b"
   )

   rem Eliminate trailing spaces
   setlocal EnableDelayedExpansion
   set spc=0
   for /L %%b in (%spcPow2%,-1,0) do (
      set /A "newSpc=spc+(1<<%%b)"
      for %%n in (!newSpc!) do if "!line:~-%%n!" equ "!spaces:~-%%n!" set "spc=%%n"
   )
   if !spc! gtr 0 for %%n in (!spc!) do set "line=!line:~0,-%%n!"

   rem Show resulting line
   if defined line echo !line!

   endlocal
)

编辑添加新解决方案

@set @x=1 // & CScript //nologo //E:JScript "%~F0" < samplefile.txt & goto :EOF
WScript.Stdout.Write(WScript.Stdin.ReadAll().replace(/(.*)\/\/ .*/g,"$1"))

将以前的代码复制到扩展名为.BAT的文件中,也就是说,它是批处理文件