验证csv文件

时间:2014-02-03 07:30:43

标签: vba vbscript

这是我的示例文件

#%cty_id1,#%ccy_id2,#%cty_src,#%cty_cd3,#%cty_nm4,#%cty_reg5,#%cty_natnl6,#%cty_bus7,#%cty_data8
690,ALL2,,AL,ALBALODMNIA,,,,
90,ALL2,,,AQ,AKNTARLDKCTICA,,,
161,IDR2,,AZ,AZLKFMERBALFKIJAN,,,,
252,LTL2,,BJ,BENLFMIN,,,,
206,CVE2,,BL,SAILFKNT BAFSDRTHLEMY,,,,
360,,,BW2,BOPSLFTSWLSOANA,,,,

问题是#%cty_cd3standard column(NOT NULL)只有2个字母的长度,但是在sql server中,记录转移到另一列,(由于btw中有额外的逗号)我如何验证一个csv文件,以确保 当有2个字符的单词只需要在4列中时?

大约有10000条记录?

一组规则定义!

Should have a standard set of delimiters for eachrow
 if not
   Check for NOT NULL values having Null values
     If found Null
       remove delimiter at the pointer

3 ,,,未被2 ,,

取代

#UPDATED:我可以知道是否可以使用脚本完成此操作吗?

更新后我只需要一个对

等记录进行操作的函数

90,ALL2,,,AQ,AKNTARLDKCTICA,,,使用正则表达式或任何其他方法更正它们并将其放回源文件中!

6 个答案:

答案 0 :(得分:4)

这里最好的选择可能是在Talend中使用tSchemaComplianceCheck组件。

example job set up

如果您使用tFileInputDelimited组件阅读该文件,然后使用您设置tSchemaComplianceCheck的{​​{1}}进行检查以使其不可为空,那么它将拒绝您的南极洲行你期望没有空的地方。

tSchemaComplianceCheck to reject rows with null 'cty_cd'

从这里你可以使用tMap,只需将字段映射到上面的字段。

tMap to sort right fielding

您应该可以根据需要轻松调整此项,可能会在拒绝行中进一步调整cty_cd并进行映射以适应。这种方法更加自我解释,当您想要适应文件结构的不同变体时,您不必处理需要复杂管理的复杂正则表达式,并且您将始终捕获所有格式良好的行。 / p>

答案 1 :(得分:3)

如果列号为no,您可以尝试删除第4列中的空字段。 4不是双字符字段,如下所示:

awk 'BEGIN {FS=OFS=","}
{
    for (i=1; i<=NF; i++) {
        if (!(i==4 && length($4)!=4))
            printf "%s%s",$i,(i<NF)?OFS:ORS
    }
}' file.csv

输出:

"id","cty_ccy_id","cty_src","cty_nm","cty_region","cty_natnl","cty_bus_load","cty_data_load"
6,"ALL",,"AL","ALBANIA",,,,
9,"ALL",,"AQ","ANTARCTICA",,,
16,"IDR",,"AZ","AZERBAIJAN",,,,
25,"LTL",,"BJ","BENIN",,,,
26,"CVE",,"BL","SAINT BARTH�LEMY",,,,
36,,,"BW","BOTSWANA",,,,
41,"BNS",,"CF","CENTRAL AFRICAN REPUBLIC",,,,
47,"CVE",,"CL","CHILE",,,,
50,"IDR",,"CO","COLOMBIA",,,,
61,"BNS",,"DK","DENMARK",,,,

注意:

  • 我们使用length($4)!=4,因为我们假设第4列中有两个字符,但我们还需要为双引号添加两个额外的字符..

答案 2 :(得分:3)

解决方案是使用前瞻性正则表达式,如前所述。为了重现您的问题,我使用了这个:

"\\,\\,\\,(?=\\\"[A-Z]{2}\\\")"

匹配三个逗号后跟两个引用的大写字母,但不包括匹配中的这些。你可能需要根据自己的需要调整一下(即任意数量的逗号而不是三个逗号)。

但是你不能直接在Talend中使用它而不会出现大量错误。以下是如何设计您的工作: job design

换句话说,您需要逐行读取文件,还没有字段。然后,在tMap内部,进行匹配和替换,如:

row1.line.replaceAll("\\,\\,\\,(?=\\\"[A-Z]{2}\\\")", ",,")

tMap definition

最后使用“,”将行标记为分隔符以获取最终的模式。你可能需要在这里和那里手动修剪引号,因为tExtractDelimitedFields不会。

这是一个输出示例(需要一些清理,ofc):

output snippet

您无需手动输入tExtractDelimitedFields的架构。使用该向导将DelimitedFile Schema记录到元数据存储库中,就像您可能已经做过的那样。您也可以将此模式用作通用模式,使其适合tExtractDelimitedField的传出连接。纯粹主义者并不是这样,但它起作用并节省时间。

关于您的UI问题,它们通常与文件编码和区域设置有关。不要太担心,他们(通常)不会影响工作执行。

编辑:这是一个示例解决方案的示例TOS作业,只需在您的项目中导入:TOS job archive

EDIT2:添加了一些截图

答案 3 :(得分:3)

以VBA为基础的方法迟到了。正则表达式的另一种方法是解析文件并在第4个字段为空时删除逗号。使用microsoft脚本运行时,可以实现代码打开文件然后读取每一行,将其复制到新的临时文件。如果4元素为空,如果是,则写入删除了额外逗号的行。然后将清理的数据复制到原始文件,并删除临时文件。这似乎有点长,但是当我根据你的样本在一个14000行的文件上测试它时,花了2秒才完成。

Sub Remove4thFieldIfEmpty()

    Const iNUMBER_OF_FIELDS As Integer = 9

    Dim str As String
    Dim fileHandleInput As Scripting.TextStream
    Dim fileHandleCleaned As Scripting.TextStream
    Dim fsoObject As Scripting.FileSystemObject
    Dim sPath As String
    Dim sFilenameCleaned As String
    Dim sFilenameInput As String
    Dim vFields As Variant
    Dim iCounter As Integer
    Dim sNewString As String

    sFilenameInput = "Regex.CSV"
    sFilenameCleaned = "Cleaned.CSV"
    Set fsoObject = New FileSystemObject

    sPath = ThisWorkbook.Path & "\"


    Set fileHandleInput = fsoObject.OpenTextFile(sPath & sFilenameInput)

    If fsoObject.FileExists(sPath & sFilenameCleaned) Then
        Set fileHandleCleaned = fsoObject.OpenTextFile(sPath & sFilenameCleaned, ForWriting)
    Else
        Set fileHandleCleaned = fsoObject.CreateTextFile((sPath & sFilenameCleaned), True)
    End If


    Do While Not fileHandleInput.AtEndOfStream
        str = fileHandleInput.ReadLine
            vFields = Split(str, ",")
            If vFields(3) = "" Then
                sNewString = vFields(0)
                For iCounter = 1 To UBound(vFields) 
                    If iCounter <> 3 Then sNewString = sNewString & "," & vFields(iCounter)
                Next iCounter
                str = sNewString
            End If
        fileHandleCleaned.WriteLine (str)
    Loop


    fileHandleInput.Close
    fileHandleCleaned.Close

    Set fileHandleInput = fsoObject.OpenTextFile(sPath & sFilenameInput, ForWriting)
    Set fileHandleCleaned = fsoObject.OpenTextFile(sPath & sFilenameCleaned)

    Do While Not fileHandleCleaned.AtEndOfStream
        fileHandleInput.WriteLine (fileHandleCleaned.ReadLine)
    Loop

    fileHandleInput.Close
    fileHandleCleaned.Close



    Set fileHandleCleaned = Nothing
    Set fileHandleInput = Nothing

    KillFile (sPath & sFilenameCleaned)

    Set fsoObject = Nothing


End Sub

答案 4 :(得分:1)

如果这是唯一的问题(如果您在字段bt_cty_ccy_id中没有逗号),那么您可以通过将文件加载到支持正则表达式的编辑器中来删除这样一个额外的逗号它取代了

^([^,]*,[^,]*,[^,]*,),(?="[A-Z]{2}")

\1

答案 5 :(得分:0)

我会质疑源系统发送给你这个文件,为什么这些额外的逗号介于某些行之间?我想你会使用逗号作为分隔符将.csv文件导入到talend。

(或另一个建议是在输入文件中要求半冒号作为列分隔符)

9, “ALL” ,,, “AQ”, “南极” ,,,,

将是

9章; “ALL”;,; “AQ”; “南极” ;;;;