关于powershell文本操作的问题



我为问一个非常基本的问题而道歉,因为我是脚本初学者。我想知道为什么我得到不同的结果从两个不同的来源与相同的格式。下面是我的示例

Id Name                      Members                      
122 RCP_VMWARE-DMZ-NONPROD    DMZ_NPROD01_111        
DMZ_NPROD01_113        
123 RCP_VMWARE-DMZ-PROD       DMZ_PROD01_110         
DMZ_PROD01_112         
124 RCP_VMWARE-DMZ-INT.r87351 DMZ_TEMPL_210.r        
DMZ_DECOM_211.r        
125 RCP_VMWARE-LAN-NONPROD    NPROD02_20             
NPROD03_21             
NPROD04_22             
NPROD06_24           

file2.txt

Id Name       Members             
4  HPUX_PROD HPUX_PROD.3
HPUX_PROD.4
HPUX_PROD.5

我正在尝试显示名称列,并使用此代码,我能够正确显示file1.txt。

PS C:Share> gc file1.txt |Select-Object -skip 1 | foreach-object { $_.split(" ")[1]} | ? {$_.trim() -ne "" }
RCP_VMWARE-DMZ-NONPROD
RCP_VMWARE-DMZ-PROD
RCP_VMWARE-DMZ-INT.r87351
RCP_VMWARE-LAN-NONPROD

但是对于file2,我得到了不同的输出。

PS C:Share> gc .file2.txt |Select-Object -skip 1 | foreach-object { $_.split(" ")[1]} | ? {$_.trim() -ne "" }
4
changing the code to *$_.split(" ")[2]}* helps to display the output correctly

然而,我想只有一个代码,可以适用于这两种情况。如果你能帮我解决这个问题,我将不胜感激。提前谢谢你……

这是因为后一个文件的格式不同。

仔细检查,可以注意到在4HPUX_PROD字符串之间有两个空格:

Id Name       Members             
4  HPUX_PROD HPUX_PROD.3
^^^^

在第一个文件中,number和string之间有一个空格:

Id Name                      Members                      
122 RCP_VMWARE-DMZ-NONPROD    DMZ_NPROD01_111 
^^^

如何解决这个问题取决于你是否需要匹配两种文件格式,或者如果另一种只是输入错误。

现有的答案很有帮助,但让我试着从概念上分解它:

  • .Split(" ")每个空格字符分割输入字符串,而您正在寻找的是用分隔(一个或多个)空格,假设您的列值可以用多个空格分隔。

    • 例如,'a b'.split(' ')导致3数组元素-'a','','b'-因为两个空格之间的空字符串也被认为是一个元素。
  • .NET[string]类型的.Split()方法基于逐字字符串或字符集,因此不允许您表达"多一个空间"的概念;作为分割标准,而PowerShell基于regex的-split操作符执行.

    • 方便地,-split单字符形式(见下文)内置了这个逻辑:它通过任何非空空格分割每个输入字符串。,同时也忽略了开头和结尾的空格,这在您的情况下完全消除了对regex的需要。

    • 这个答案将-split操作符与字符串类型的.Split()方法进行比较和对比,并说明通常使用前者

因此,一个有效的解决方案(对于两个输入文件)是:

Get-Content .file2.txt | Select-Object -Skip 1 |
Foreach-Object { if ($value = (-split $_)[1]) { $value } }

注意:

  • 如果感兴趣的列包含一个值(至少一个非空白字符),那么必须在列之前的所有列才能使该方法工作。此外,列值本身不能有嵌入的空白(对于您的示例输入来说是正确的)。

  • if条件提取第二列值((-split $_)[1])并将其分配给变量($value =),其值然后隐式地用作布尔值:

    • 任何非空字符串隐式地为$true,在这种情况下,提取的值输出到相关块({ $value });相反,字符串将导致没有输出。

    • 有关PowerShell隐式到布尔值转换的一般概述,请参阅本答案的底部部分。

由于这有点像csv输出与空格作为分隔符(但不完全),我认为你可以使用ConvertFrom-Csv在这:

# read the file as string array, trim each line and filter only the lines that
# when split on 1 or more whitespace characters has more than one field
# then replace the spaces by a comma and treat it as CSV
# return the 'Name' column only
(((Get-Content -Path 'D:Testfile1.txt').Trim() | 
Where-Object { @($_ -split 's+').Count -gt 1 }) -replace 's+', ',' | 
ConvertFrom-Csv).Name

更短,但因为您只在Name列之后,所以也可以这样做:

((Get-Content -Path 'D:Testfile2.txt').Trim() -replace 's+', ',' | ConvertFrom-Csv).Name -ne ''

file1

输出
RCP_VMWARE-DMZ-NONPROD
RCP_VMWARE-DMZ-PROD
RCP_VMWARE-DMZ-INT.r87351
RCP_VMWARE-LAN-NONPROD

file2的输出

HPUX_PROD

最新更新