Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 使用powershell在数组中捕获正则表达式匹配项_Regex_Macos_Powershell_Outlook_Contacts - Fatal编程技术网

Regex 使用powershell在数组中捕获正则表达式匹配项

Regex 使用powershell在数组中捕获正则表达式匹配项,regex,macos,powershell,outlook,contacts,Regex,Macos,Powershell,Outlook,Contacts,我们有一个从mac用户计算机导出的大型.vcf 导出联系人的过程产生了一个.vcf文件,该文件将所有联系人集中到一个文件中。我使用notepad++将“BEGIN:”的所有实例替换为“\nBEGIN:”,这样我今晚就可以睡觉了 计划是将每个匹配到我的reg表达式的字符串放入一个数组中,然后将每个字符串输出到许多唯一命名的.vcf文件中 (我计划稍后将字符串“BEGIN:VCARD”和“END:VCARD”添加回每个文件的开头和结尾。) 这是我们正在处理的数据的剪报: BEGIN:VCARD VE

我们有一个从mac用户计算机导出的大型.vcf

导出联系人的过程产生了一个.vcf文件,该文件将所有联系人集中到一个文件中。我使用notepad++将“BEGIN:”的所有实例替换为“\nBEGIN:”,这样我今晚就可以睡觉了

计划是将每个匹配到我的reg表达式的字符串放入一个数组中,然后将每个字符串输出到许多唯一命名的.vcf文件中

(我计划稍后将字符串“BEGIN:VCARD”和“END:VCARD”添加回每个文件的开头和结尾。)

这是我们正在处理的数据的剪报:

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;;;;
TEL;type=CELL;type=VOICE;type=pref:+18005555555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
END:VCARD

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;<blah@company.org>;;;
FN:<blah@company.org>
item1.EMAIL;type=INTERNET;type=pref:blah@company.org
item1.X-ABLabel:_$!<Other>!$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
END:VCARD

...
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
电话;类型=细胞;类型=语音;类型=首选项:+1800555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
完:VCARD
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
FN:
项目1.电子邮件;类型=互联网;type=pref:blah@company.org
项目1.X-ABLabel:$$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
完:VCARD
...
我接近下面的代码,但它只返回第一个匹配

$String = cat C:\temp\contacts.txt            
$Regex = [Regex]::new("(?<=BEGIN:VCARD)(.*?)(?=END:VCARD)")            
$Match = $Regex.Match($String)            
if($Match.Success)            
{            
    $Match.Value            
}
$String=cat C:\temp\contacts.txt

$Regex=[Regex]::new((?您只要求在发布的每个代码块中进行一次匹配。 您可能希望改用正则表达式匹配

这会让你得到你想要的:

$VCardData = @'
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;;;;
TEL;type=CELL;type=VOICE;type=pref:+18005555555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
END:VCARD

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;<blah@company.org>;;;
FN:<blah@company.org>
item1.EMAIL;type=INTERNET;type=pref:blah@company.org
item1.X-ABLabel:_$!<Other>!$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
END:VCARD
'@

# Use RegEx match to search for strings across line breaks. 
$VcardRegEx = '(?s)(?<=BEGIN:VCARD).*?(?=END:VCARD)'

# Select all matches
[RegEx]::Matches($VCardData,$VcardRegEx).Value

#results

VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;;;;
TEL;type=CELL;type=VOICE;type=pref:+18005555555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson


VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;<blah@company.org>;;;
FN:<blah@company.org>
item1.EMAIL;type=INTERNET;type=pref:blah@company.org
item1.X-ABLabel:_$!<Other>!$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
$VCardData=@'
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
电话;类型=小区;类型=语音;类型=首选:+1800555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
完:VCARD
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
FN:
项目1.电子邮件;类型=互联网;类型=首选项:blah@company.org
项目1.X-ABLabel:$$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
完:VCARD
'@
#使用正则表达式匹配搜索跨换行符的字符串。

$VcardRegEx='(?s)(?此PowerShell脚本

  • 使用非消耗正则表达式将输入拆分为块 使用
    开始:VCARD
  • 它检查内部是否有UID,并相应地命名输出文件
  • 所有其他名称均命名为
    NoUID#0000.vcf
    ,并带有递增计数器

编辑简化变量,仅为输出文件名提供一个计数器

## Q:\Test\2018\06\02\SO_50659915.ps1
$InFile = '.\sample.vcf'
$Delimiter = 'BEGIN:VCARD'
$Split     = "(?!^)(?=$Delimiter)"
(Get-Content $InFile -Raw) -split $Split | ForEach-Object {$I=0}{
    $I++
    $_ | Out-File -FilePath ("Whatever{0:0000}.vcf" -f $I) -Encoding UTF8
}

##Q:\Test\2018\06\02\SO_50659915.ps1
$InFile='.\sample.vcf'
$Delimiter='BEGIN:VCARD'
#如果分隔符包含将被解释为特殊RE字符的字符
#需要手动或使用以下命令对它们进行转义
#$Escape=[regex]::Escape($Delimiter)
$Split=“(?!^)(?=$Delimiter)”
(获取内容$infle-Raw)-split$split | ForEach对象{$I=0}{
如果($匹配'UID:(?[0-9a-f\-]{32})){
$124; Out File-FilePath($Matches.UID+“.vcf”)-编码UTF8
}否则{
$I++
$124; Out File-FilePath(“NoUID{0:0000}.vcf”-f$I)-编码UTF8
}
}
结果输出示例:

> ls

    Directory: Q:\Test\2018\06\02

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-06-03     20:05            236 3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
-a----       2018-06-03     20:05            311 5ad596-a879-4c98-9f56-2ef90efe32.vcf
-a----       2018-06-03     20:05            236 NoUID#0001.vcf
-a----       2018-06-03     20:05            311 NoUID#0002.vcf
-a----       2018-06-02     21:45            537 sample.vcf
-a----       2018-06-03     19:41            416 SO_50659915.ps1

> Get-Content .\3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;;;;
TEL;type=CELL;type=VOICE;type=pref:+18005555555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
END:VCARD


> Get-Content .\5ad596-a879-4c98-9f56-2ef90efe32.vcf
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;<blah@company.org>;;;
FN:<blah@company.org>
item1.EMAIL;type=INTERNET;type=pref:blah@company.org
item1.X-ABLabel:_$!<Other>!$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
END:VCARD

>
>ls
目录:Q:\Test\2018\06\02
模式LastWriteTime长度名称
----                -------------         ------ ----
-a----2018-06-03 20:05 236 3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
-a----2018-06-03 20:05 311 5ad596-a879-4c98-9f56-2ef90efe32.vcf
-a---2018-06-03 20:05 236努伊德#0001.vcf
-a----2018-06-03 20:05 311努伊德#0002.vcf
-a----2018-06-02 21:45 537 sample.vcf
-a----2018-06-03 19:41 416 SO_50659915.ps1
>获取内容。\3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
电话;类型=小区;类型=语音;类型=首选:+1800555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
完:VCARD
>获取内容。\5ad596-a879-4c98-9f56-2ef90efe32.vcf
开始:VCARD
版本:3.0
PRODID:-//苹果公司//Mac OS X 10.13.4///EN
N;;;;
FN:
项目1.电子邮件;类型=互联网;类型=首选项:blah@company.org
项目1.X-ABLabel:$$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
完:VCARD
>
LotPings击败了我。 不管怎样,这是我的解决办法

# Enter the full path and filename of your large combined vcf file here
$InputFile  = '<The full path and filename to your vcf file>'
# The path where yhou want the output vcf files. Below defaults to a folder 'VCards' within your Temp directory
$OutputPath = Join-Path $env:TEMP 'VCards'

# Read the input file in a single string
$VCardData  = Get-Content $InputFile -Raw

# Create the output folder if it does not already exist
if (!(Test-Path $OutputPath -PathType Container)) {
    New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null
}

# Use RegEx match to search for strings across line breaks.
# This regex will keep the "BEGIN:VCARD" and "END:VCARD" for each array element intact 
$VcardRegex = '(?s)((?:BEGIN:VCARD).*?(?:END:VCARD))'
# This regex is for parsing out the UID value of the vcard if present
$UidRegex   = '\b(?:UID:)(?:urn:)?(?:uuid:)?([0-9a-f\-]*)\b'

# Select all matches
$VCardArray = [RegEx]::Matches($VCardData,$VcardRegex).Value

# Save results to $OutputPath as separate .vcf files
# using the UID value as filename. If no UID is found in the VCard element,
# a safety name is generated using a simple counter $i.

# Each file is encoded in UTF-8 encoding. If you use the Set-Content commandlet with option -Encoding UTF8
# it will create files prefixed with a byte order mark (BOM).
# Because it is usually advisable to create the file without the BOM, i use [System.IO.File]::WriteAllText
# using an encoding object

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $false

$i = 0
$VCardArray | ForEach-Object {
    if ($_ -match $UidRegex) {
        $fileName = $matches[1] + '.vcf'
    } 
    else {
        $fileName = 'Vcard_{0:000}.vcf' -f $i++
    }
    $fileOut = Join-Path $OutputPath $fileName

    try {
    [System.IO.File]::WriteAllText($fileOut, $_, $Utf8NoBomEncoding)
    Write-Host "Saved file '$fileOut'"
    }
    catch {
    Write-Error "Could not write file '$fileOut':`r`n$($_.Exception.Message)"
    }
}
#在此处输入大型组合vcf文件的完整路径和文件名
$InputFile=''
#您希望输出vcf文件的路径。以下默认为临时目录中的“VCards”文件夹
$OutputPath=连接路径$env:TEMP'VCards'
#以单个字符串读取输入文件
$VCardData=获取内容$InputFile-原始
#如果输出文件夹不存在,请创建该文件夹
if(!(测试路径$OutputPath-路径类型容器)){
新建项-ItemType目录-Force-Path$OutputPath | Out Null
}
#使用正则表达式匹配搜索跨换行符的字符串。
#这个正则表达式将保持每个数组元素的“BEGIN:VCARD”和“END:VCARD”完好无损
$VcardRegex=“(?:开始:VCARD)。*?(?:结束:VCARD))”
#此正则表达式用于解析vcard的UID值(如果存在)
$UidRegex='\b(?:UID:)(?:urn:)(?:uuid:)([0-9a-f\-]*)\b'
#选择所有匹配项
$VCardArray=[RegEx]::匹配($VCardData,$VcardRegex).Value
#将结果作为单独的.vcf文件保存到$OutputPath
#使用UID值作为文件名。如果在VCard元素中找不到UID,
#使用简单的计数器$i生成安全名称。
#每个文件都以UTF-8编码。如果使用Set Content命令和选项-ENCONDING UTF8
#它将创建以字节顺序标记(BOM)为前缀的文件。
#因为通常建议创建没有BOM表的文件,所以我使用[System.IO.file]::writealText
#使用编码对象
$Utf8NoBomEncoding=新对象System.Text.UTF8Encoding$false
$i=0
$VCardArray | ForEach对象{
如果($\匹配$UidRegex){
$fileName=$matches[1]+'.vcf'
} 
否则{
$fileName='Vcard{0:000}.vc
## Q:\Test\2018\06\02\SO_50659915.ps1
$InFile = '.\sample.vcf'

$Delimiter = 'BEGIN:VCARD'
# If the Delimiter contains chars that would be interpreted as special RE chars
# they need to be escaped, either manually or with the following command
# $Escaped   = [regex]::Escape($Delimiter)
$Split     = "(?!^)(?=$Delimiter)"

(Get-Content $InFile -Raw) -split $Split | ForEach-Object {$I=0}{
    if ($_ -match 'UID:(?<UID>[0-9a-f\-]{32})'){
        $_ | Out-File -FilePath ($Matches.UID+".vcf") -Encoding UTF8
    } else {
        $I++
        $_ | Out-File -FilePath ("NoUID#{0:0000}.vcf" -f $I) -Encoding UTF8
    }
}
> ls

    Directory: Q:\Test\2018\06\02

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-06-03     20:05            236 3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
-a----       2018-06-03     20:05            311 5ad596-a879-4c98-9f56-2ef90efe32.vcf
-a----       2018-06-03     20:05            236 NoUID#0001.vcf
-a----       2018-06-03     20:05            311 NoUID#0002.vcf
-a----       2018-06-02     21:45            537 sample.vcf
-a----       2018-06-03     19:41            416 SO_50659915.ps1

> Get-Content .\3fe8e0-421c-4c6a-bfa-38c75df8c07.vcf
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;;;;
TEL;type=CELL;type=VOICE;type=pref:+18005555555
UID:3fe8e0-421c-4c6a-bfa-38c75df8c07
X-ABUID:3FE8490-421C-4C6A-B2FA-38C15DF8C07:ABPerson
END:VCARD


> Get-Content .\5ad596-a879-4c98-9f56-2ef90efe32.vcf
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//Mac OS X 10.13.4//EN
N:;<blah@company.org>;;;
FN:<blah@company.org>
item1.EMAIL;type=INTERNET;type=pref:blah@company.org
item1.X-ABLabel:_$!<Other>!$_
UID:5ad596-a879-4c98-9f56-2ef90efe32f
X-ABUD:DB5C20C-6DFC-450F-A752-D57964F6F3A:ABPerson
END:VCARD

>
# Enter the full path and filename of your large combined vcf file here
$InputFile  = '<The full path and filename to your vcf file>'
# The path where yhou want the output vcf files. Below defaults to a folder 'VCards' within your Temp directory
$OutputPath = Join-Path $env:TEMP 'VCards'

# Read the input file in a single string
$VCardData  = Get-Content $InputFile -Raw

# Create the output folder if it does not already exist
if (!(Test-Path $OutputPath -PathType Container)) {
    New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null
}

# Use RegEx match to search for strings across line breaks.
# This regex will keep the "BEGIN:VCARD" and "END:VCARD" for each array element intact 
$VcardRegex = '(?s)((?:BEGIN:VCARD).*?(?:END:VCARD))'
# This regex is for parsing out the UID value of the vcard if present
$UidRegex   = '\b(?:UID:)(?:urn:)?(?:uuid:)?([0-9a-f\-]*)\b'

# Select all matches
$VCardArray = [RegEx]::Matches($VCardData,$VcardRegex).Value

# Save results to $OutputPath as separate .vcf files
# using the UID value as filename. If no UID is found in the VCard element,
# a safety name is generated using a simple counter $i.

# Each file is encoded in UTF-8 encoding. If you use the Set-Content commandlet with option -Encoding UTF8
# it will create files prefixed with a byte order mark (BOM).
# Because it is usually advisable to create the file without the BOM, i use [System.IO.File]::WriteAllText
# using an encoding object

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $false

$i = 0
$VCardArray | ForEach-Object {
    if ($_ -match $UidRegex) {
        $fileName = $matches[1] + '.vcf'
    } 
    else {
        $fileName = 'Vcard_{0:000}.vcf' -f $i++
    }
    $fileOut = Join-Path $OutputPath $fileName

    try {
    [System.IO.File]::WriteAllText($fileOut, $_, $Utf8NoBomEncoding)
    Write-Host "Saved file '$fileOut'"
    }
    catch {
    Write-Error "Could not write file '$fileOut':`r`n$($_.Exception.Message)"
    }
}