代码之家  ›  专栏  ›  技术社区  ›  av abhishiek

验证shell中列的唯一值

  •  0
  • av abhishiek  · 技术社区  · 8 年前

    我得到一个输入文件供应商。csv中有一个名为retailer的列。 我有一个预定义的有效零售商值列表,这些值是a、b、c。如果零售商列中有“d”,我将不得不采取一些措施,主要是将其回显到日志中,停止处理并通知用户。

    到目前为止,我已经做了以下工作

    f1=/stage/Scripts/ecommerce/vendor/final*.csv
    k=`cut -d, -f1 $f1 |sort -u`
    echo $k
    

    这让我

    a b c d
    

    以上订单未用逗号分隔

    对于上述情况,我可以将有效值a b c存储在文件或字符串中

    我现在怎么结账?这是最好的方式吗

    有效值为 ALB/SFY Total Ecom TA Peapod Total Ecom TA Target Total Ecom TA

    现有数据包含以下唯一数据点 ALB/SFY Total Ecom TA Hy-Vee Total Ecom TA Peapod Total Ecom TA Target Total Ecom TA

    因此,“Hy Vee Total Ecom TA”是无效值。

    这是我对grep的尝试

    $ echo $s
    ALB/SFY Total Ecom TA Peapod Total Ecom TA Target Total Ecom TA
    
     echo $k
    ALB/SFY Total Ecom TA Hy-Vee Total Ecom TA Peapod Total Ecom TA Target Total Ecom TA
    
    grep -v "$s" "$k"
    

    它给了我一个错误

    grep: ALB/SFY Total Ecom TA
    Hy-Vee Total Ecom TA
    Peapod Total Ecom TA
    Target Total Ecom TA: No such file or directory
    

    一些解决方案为我指明了正确的方向,在R中,我将按照以下方式执行上述任务

    valid_values = ['a','b','c']
    invalid_retailer = unique(vendorfile$retailer) %not% in valid_values 
    

    我试图在shell中复制相同的过程,因此我使用了cut和grep。

    3 回复  |  直到 8 年前
        1
  •  3
  •   Riyas S    8 年前

    尝试awk命令,这是非常精致的。

    awk -F',' '{if (($1 == "a") || ($1 == "b") || ($1 == "c") || ($1 == "d")) print $0 }' /stage/Scripts/ecommerce/vendor/final*.csv
    

    其他方式::

    我们可以在单独的文件中逐行提供所有零售商id,例如 retailer.txt . 的内容 零售商txt文件 就像

    a
    b
    

    为了打印这些行的第一个字段(由,)与中的零售商id匹配 零售商txt文件 ,使用以下命令:

    awk -F',' 'FNR==NR{$1=a[$1];next} ($1 in a)' retailer.txt final*.csv
    
        2
  •  1
  •   tripleee    8 年前

    也许是这样的?

    awk -F, 'NR==FNR { ++a[$1]; next }
        !a[$1] { print FILENAME ":" FNR ": Invalid label " $1 >>"/dev/stderr" }' valid.txt final*.csv
    

    哪里 valid.txt 包含有效标签,每行一个。

    的一般模式 awk 'NR==FNR { ++a[$1] }' 是将一组文件中的第一个读取到内存中的数组中,然后在脚本的其余部分与其他输入文件中的字段执行某种连接(在数据库意义上)的常用方法。Awk一次只处理一行,所以其他文件可以任意大。不过,您确实需要能够将第一个文件中的数据存储在内存中。

    与您的基本 cut + grep 我们的尝试是,我们可以打印整个输入行,而不仅仅是告诉您哪些标签无效,然后让您返回并手动找出文件中实际包含冲突的行。

    切向上,您的 格雷普 尝试有许多问题。首先,如果您处理的不是玩具数据,那么您希望避免将数据存储在shell变量中。其次,你可能想调整你的选择来告诉别人 格雷普 您希望逐字匹配文本( -F --没有这个, a.c 比赛 abc 因为点是一个regex通配符,例如),并且您希望匹配覆盖整行( -x --没有这个, b 比赛 美国广播公司 因为它是一个子字符串)。

    cut -d, -f1 final*.csv | sort -u |
    grep -vxFf valid.txt
    

    这个 -f 文件名 选项表示从文件中读取模式,并且不使用其他文件名, 格雷普 处理标准输入(在这种情况下,来自管道)。

        3
  •  -1
  •   romaric crailox    8 年前

    grep 不能做你想做的事?

    如果我理解,打电话 格雷普 在您的csv文件上,使用好的regex可以打印出所有与错误零售商的行。 您需要选择一个强正则表达式来防止误报匹配,但我需要输入示例来帮助您。。。

    或者,如果正则表达式不能防止误报,则可以使用grep after cut命令,如下所示:

    for bad_retailer in $(cut -d, -f1 $f1 | grep d) ; do echo $bad_retailer ; done
    

    d是坏零售商的名字。

    如果要跟踪多个不良零售商,可以使用 grep -E "d|g|h" ,以及坏零售商的d、g和h名称。