2013-01-18 71 views
5

我只需要在文本文件中搜索第一行和最后一行来查找“ - ”并将其删除。 我该怎么办? 我试过选择字符串,但我不知道找到第一行和最后一行,只从那里删除“ - ”。如何搜索文本文件的第一行和最后一行?

这里是文本文件看起来像:

% 01-A247M15 G70 
N0001 G30 G17 X-100 Y-100 Z0 
N0002 G31 G90 X100 Y100 Z45 
N0003 ; --PART NO.: NC-HON.PHX01.COVER-SHOE.DET-1000.050 
N0004 ; --TOOL: 8.55 X .3937 
N0005 ; 
N0006 % 01-A247M15 G70 

像这样的事情?

$1 = Get-Content C:\work\test\01.I 

$1 | select-object -index 0, ($1.count-1) 

回答

5

好了,所以在这找了一段时间后,我决定必须有一种方法用一个衬垫做到这一点。那就是:

(gc "c:\myfile.txt") | % -Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)} -Process {if ($_ -eq $test[0] -or $_ -eq $test[-1]) { $_ -replace "-" } else { $_ }} | Set-Content "c:\myfile.txt" 

这是什么,这是做了细分:

首先,对于那些现在熟悉的别名。我只是把他们因为命令是足够长的时间,因为它是,所以这有助于保持便于管理:

  1. gc意味着Get-Content
  2. %意味着Foreach
  3. $_是当前管道值(这ISN “T的别名,但我想我会定义它,因为你说你是新的)

好了,现在这里是在此发生的事情:

  1. (gc "c:\myfile.txt") | - >获取的c:\myfile.txt的内容并把它上下行
  2. % - >是否foreach循环
  3. -Begin {$test = (gc "c:\myfile.txt" | select -first 1 -last 1)}(通过每个项目单独的管道进入) - >这是它是一个开始块,在它进入管道之前,它在这里运行所有的东西。它将c:\myfile.txt的第一行和最后一行加载到数组中,以便我们检查第一个和最后一个项目
  4. -Process {if ($_ -eq $test[0] -or $_ -eq $test[-1]) - >这将对管道中的每个项目执行检查,检查它是否是第一个或最后一个项目文件
  5. { $_ -replace "-" } else { $_ } - >如果它是第一个或最后一个,但它的替代品,如果它不是,它只是离开它单独
  6. | Set-Content "c:\myfile.txt" - >这使新值回文件。

请参看下面的网站的详细信息,其中的每一项:在Foreach的

Get-Content uses
Get-Content definition
Foreach
The Pipeline
Begin and Process部分(这通常是自定义的功能,但他们也在foreach循环中工作)
If ... else陈述
Set-Content

所以我在想,如果你想要做什么这许多文件,或想经常这样做。我决定做一个能够完成你所问的功能。这里是功能:

function Replace-FirstLast { 
    [CmdletBinding()] 
    param(
     [Parameter(` 
      Position=0, ` 
      Mandatory=$true)] 
     [String]$File, 
     [Parameter(` 
      Position=1, ` 
      Mandatory=$true)] 
     [ValidateNotNull()] 
     [regex]$Regex, 
     [Parameter(` 
      position=2, ` 
      Mandatory=$false)] 
     [string]$ReplaceWith="" 
    ) 

Begin { 
    $lines = Get-Content $File 
} #end begin 

Process { 
    foreach ($line in $lines) { 
     if ($line -eq $lines[0] ) { 
      $lines[0] = $line -replace $Regex,$ReplaceWith 
     } #end if 
     if ($line -eq $lines[-1]) { 
      $lines[-1] = $line -replace $Regex,$ReplaceWith 
     } 
    } #end foreach 
}#End process 

end { 
    $lines | Set-Content $File 
}#end end 

} #end function 

这将创建一个命令叫做Replace-FirstLast。它会被称为是这样的:

Replace-FirstLast -File "C:\myfiles.txt" -Regex "-" -ReplaceWith "NewText" 

-Replacewith是可选的,如果是空白的,将直接删除(的""默认值)。 -Regex正在寻找一个正则表达式来匹配你的命令。有关将其放至您的个人资料检查信息this article

请注意:如果文件非常大(几个GB),这是不是最好的解决办法。这会导致整个文件存储在内存中,这可能会导致其他问题。

+0

很好的答案,但请注意,如果文件变大,则在begin语句中使用'get-content -First 1'和'-Last 1'会更好,因此您不必将xxGB文件保留在处理时的内存。 –

+0

确实如此,但是我们又回到了没有把整个文件传回去的问题,只是第一行和最后一行。 – Nick

+0

没有。我在开头声明“foreach -begin {..here ...}'中说过。 :) –

6

尝试:

$txt = get-content c:\myfile.txt 
$txt[0] = $txt[0] -replace '-' 
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-' 
$txt | set-content c:\myfile.txt 
+2

错别字:$ a - > $ txt(最后一行)。 $ txt [1] - > $ txt [0] :-) –

+0

Hoo ..谢谢!现在修好! –

+1

nope ..仍然是最后一行(wtf是$ a?)hehe:P –

1

可以使用select-object cmdlet来帮助你这一点,因为get-content基本上吐出了一个文本文件作为一个巨大的数组。

因此,你可以做这样的事情

get-content "path_to_my_awesome_file" | select -first 1 -last 1 

要删除后的破折号,您可以使用-Replace开关找到仪表板和删除。这比使用System.String.Replace(...)方法更好,因为它可以匹配正则表达式并替换整个字符串数组!

这将是这样的:

# gc = Get-Content. The parens tell Powershell to do whatever's inside of it 
# then treat it like a variable. 
(gc "path_to_my_awesome_file" | select -first 1 -last 1) -Replace '-','' 
+0

我也这么想,我发现的唯一问题是他需要整个阵列。如果您试图将其回送到文件中,它将只包含第一行和最后一行,而不是整个文件的第一行和最后一行发生更改。 – Nick

+1

另外,它应该是'gc'作为'Get-Content'的别名。 'gci'是'Get-ChildItem'的别名 – Nick

+0

感谢您纠正我;我经常使用'cat',有时我忘记了cmdlet的全名。 :) –

0

一个清洁的回答以上:

$Line_number_were_on = 0 
$Awesome_file = Get-Content "path_to_ridiculously_excellent_file" | %{ 
    $Line = $_ 
    if ($Line_number_were_on -eq $Awesome_file.Length) 
     { $Line -Replace '-','' } 
    else 
     { $Line } ; 
    $Line_number_were_on++ 
} 

我喜欢的俏皮话,但我发现,可读性往往当我把简洁了功能有时会受到影响。如果你正在做的事情将成为其他人将阅读/维护的脚本的一部分,可读性可能需要考虑。

+0

这个脚本有几个问题。首先,它只能在最后一行工作,而不是首先和最后一行。其次,'$ line'永远不会放回任何东西,所以工作完成后丢失,永远放回到文件中。 – Nick

0

继尼克的回答是:我需要做这在目录树中的所有文本文件,这是我现在使用什么:

Get-ChildItem -Path "c:\work\test" -Filter *.i | where { !$_.PSIsContainer } | % { 
$txt = Get-Content $_.FullName; 
$txt[0] = $txt[0] -replace '-'; 
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] -replace '-'; 
$txt | Set-Content $_.FullName 
} 

,它看起来像它现在运作良好。

0

如果您的文件非常大,您可能不想读取整个文件以获取最后一行。 gc -Tail会很快为您获得最后一行。

function GetFirstAndLastLine($path){ 

    return New-Object PSObject -Property @{   
     First = Get-Content $path -TotalCount 1 
     Last = Get-Content $path -Tail 1 
     } 
} 

GetFirstAndLastLine "u_ex150417.log" 

我想这对一个20 GB的日志文件,并将其立即返回。读取文件需要几个小时。

如果您想保留所有切除的内容并且只想从最后删除,您仍然需要阅读该文件。使用-Tail是检查它是否存在的快速方法。

我希望它能帮助。

0

工艺简单: 替换$ file.txt的与你的文件名

获取内容$ file_txt | Select-Object -last 1

相关问题