2012-10-16 50 views
1

我有一台Linux服务器,将在一天中生成需要插入到数据库中的多个文件;使用Putty我可以sftp他们到运行SQL 2008的服务器。问题是文件本身的结构,它有一个文本的字符串将被放置在不同的列,但批量插入在SQL试图把它全部到一列而不是六列。 Powershell可能不是最好的方法,但我已经在几个网站上看到它如何找到并替换或附加到行尾,它是否可以计数和插入?计算字符串中的字符,然后使用PowerShell插入分隔符

所以文件看起来像这样:'18240087A + 17135555555 3333333333',其中18,24,00,87,A是不同的列,那么在A和+之间有一个空格,即字符数10 -19是另一列,则字符20-30是列,字符31-36是新列的空格等等。所以我想插入一个'|'或一个',',以便sql能够理解列结束的位置。 PowerShell可以随机计数吗?


这可能不是回应所有回答的方式,我提前道歉。由于这是我的第一个PowerShell脚本,我很欣赏你们每个人的意见。这是生成CDR记录的Avaya SIP服务器,我必须从服务器中提取CDR记录,并将其插入SQL以供稍后报告。导出的文件是这样的:

18:47 10/15

18470214A 14434444444 3013777777 CME-SBC HHHH-CM 4 M00 0

起初我只是想删除第一线并运行

$测试=获取内容C::针对输出,这是我从Kieranties后修饰的脚本\共享\ CDR \ testCDR.txt

$图案=“^(({2})。 {2})({1})({2})({1})({1})\ S *({15})({10})\ S *({7 })\ S *(。{7})\ S *(。{1})\ S *(。{1})({如果($ test -match $ pattern){ $ result = $ matches.Values | {1})(。{1})\ s *(。*)$“

选择 - 第一($ matches.Count-1)

[array]::Reverse($result, 0, $result.Length) 

$result = $result -join "|"  
$result | Out-File c:\Share\CDR\results1.txt 

}

但后来我意识到我需要的第一线,因为它包含的日期。不过,我可以尝试以另一种方式工作。

我现在也看到,有些时候,该文件包含2个或更多的行CDR信息,如:

18:24 10/15

18240087A 14434444444 3013777777 CME-SBC HRSA- CM 4 M00 0

18240096A 14434444445 3013777778 CME-SBC HRSA-CM 4 M00 0

尽管名为.ps1文件我做不给第二个字符串,所以我尝试添加在此:

的foreach($数据在$测试) { $数据= $数据-split( '')

和它无法运行。我怎样才能做多行(可能是第一行)?如果您知道可以提供帮助的教程,那也非常感谢!

回答

0

这是一个办法(真难看IMO,我认为它可以做得更好):

$a = '18240087A +17135555555 3333333333' 
$b = @(($a[0..1] -join ''), ($a[2..3] -join ''), ($a[4..5] -join ''), 
    ($a[6..7] -join ''), ($a[8] -join ''), ($A[10..19] -join ''), 
    ($a[20..30] -join ''), ($a[31..36] -join '')) 
$c = $b -join '|' 
$c 
18|24|00|87|A|+171355555|55 33333333|33 

我不知道,如果是分辩分裂你的需要,但在每[x..y]可以更改值做什么更适合你的需要。 Remenber该字符数组是基于0的,然后第一个字符是0,依此类推。

+0

感谢您的回答! –

0

我不太遵循拆分规则。无论如何,什么样的软件写入文本文件?也许它可以被指示改变结构?

话虽这么说,插入管道是.Insert()

$a= '18240087A +17135555555 3333333333' 
$a.Substring(0, $a.IndexOf('+')).Insert(2, '|').insert(5,'|').insert(8, '|').insert(11, '|').insert(13, '|') 
# Output: 18|24|00|87|A| 

# Rest of the line: 
$a.Substring($a.IndexOf('+')+1) 
# Output: 17135555555 3333333333 

很容易,从那里你可以继续分裂行数据的其余部分。

0

我根据您的响应提高了我的答案(注意,这可能是最好的,你更新你的实际问题,包括信息!)

的好处在PowerShell中约Get-Content是返回的内容以数组分割在行字符的末尾。再加上允许从一个数组中进行多次赋值,并最终得到一些整洁的代码。

下面的函数根据您的原始答案的修改版本来处理每一行。然后它被处理文件的函数包装。

这会读取给定文件,将第一行设置为$date,将其余内容设置为$content。然后它创建一个输出文件将日期添加到输出,然后循环执行正则表达式检查的其余内容,并在检查成功时添加内容的分析版本。

Function Parse-CDRFileLine { 
    Param(
     [string]$line 
    ) 

    $pattern = "^(.{2})(.{2})(.{1})(.{2})(.{1})(.{1})\s*(.{15})(.{10})\s*(.{7})\s*(.{7})\s*(.{1})\s*(.{1})(.{1})(.{1})\s*(.*)$" 
    if($line -match $pattern){ 
     $result = $matches.Values | select -first ($matches.Count-1) 
     [array]::Reverse($result, 0, $result.Length) 
     $result = $result -join "|"  
     $result 
    } 
} 



Function Parse-CDRFile{ 
    Param(
     [string]$filepath 
    )  

    # Read content, setting first line to $date, the rest to $content 
    $date,$content = Get-Content $filepath  

    # Create the output file, overwrite if neccessary 
    $outputFile = New-Item "$filepath.out" -ItemType file -Force 

    # Add the date line 
    Set-Content $outputFile $date 

    # Process the rest of the content 
    $content | 
     ? { -not([string]::IsNullOrEmpty($_)) } | 
     % { Add-Content $outputFile (Parse-CDRFileLine $_) } 
} 

Parse-CDRFile "C:\input.txt" 

我用你的样品输入,结果我得到的是:

18:24 10/15 
18|24|0|08|7|A|+14434444444 30|13777777 C|ME-SBC |HRSA-CM|4|M|0|0|0 
18|24|0|09|6|A|+14434444445 30|13777778 C|ME-SBC |HRSA-CM|4|M|0|0|0 

有资源数量惊人的在那里,但一个我特别建议是道格拉斯Finkes Powershell for Developers这是短期,简洁和全面这些信息可以让你用正确的心态思考Powershell

+0

感谢您的回答!我用你的建议,并修改了一些。 –

1

PowerShell是一款非常棒的工具,我喜欢它,它可以做很多事情。我发现您正在使用SQL Server 2008.根据您在服务器上运行的SQL Server版本的不同,它很可能具有SQL Server Integration Services(SSIS),它是一种提取,转换和加载(ETL)工具以帮助在许多情况下迁移数据,例如您的数据。你在这里描述的文件听起来像一个固定宽度的文件,SSIS可以轻松处理和导入,SQL Server有很好的方法来自动化负载,如果这是反复出现的需求(听起来像),包括sftp任务的自动化,甚至运行PowerShell脚本作为ETL的一部分(我已经做了几次)。

如果您的文件确实是固定宽度,并且您想使用PowerShell将其转换为分隔文件,那么您在答案中使用的正则表达式方法运行良好,或者有几种使用System.String方法的方法。 insert()允许你在你的行中插入一个使用字符索引的分隔字符(使用Get-Content读取文件并为每行创建一个String对象,然后使用Foreach循环或Foreach-Object和管道循环它们) 。稍微更困难的方法是使用.Substring()方法。您可以使用Substring构建新的String行来提取每列,并将这些值与分隔符连接起来。对于刚接触PowerShell的人来说,这可能很多,但学习和掌握PowerShell的最好方法之一是练习用多种方式编写相同的脚本。您可以学习可能解决您将来可能遇到的其他问题的新技术。

相关问题