我为问一个非常基本的问题而道歉,因为我是脚本初学者。我想知道为什么我得到不同的结果从两个不同的来源与相同的格式。下面是我的示例
中
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
然而,我想只有一个代码,可以适用于这两种情况。如果你能帮我解决这个问题,我将不胜感激。提前谢谢你……
这是因为后一个文件的格式不同。
仔细检查,可以注意到在4
和HPUX_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