检查第1列的值是否在第2列的任何位置,将结果写入第3列(CSV文档)

时间:2019-04-18 10:09:57

标签: regex bash csv comparison sh

我正在寻找一种方法来检查第一列(产品名称)的值是否存在于第二列(产品变体)和将结果(匹配/不匹配)写入CSV文档的第三列中。

由于此任务可能会重复发生,因此我想开始为此编写脚本。

csv文档当前的结构如下(第三列不包含匹配项):

"PRODUCT";"VARIANT";"MATCH"
"100 DG";"black";""
"100 DG";"100 DG black";""
"100 DG";"silver 100 DG";""
"100 DG";"silver 100 DG US edition";""
...

结果应如下所示:

"PRODUCT";"VARIANT";"MATCH"
"100 DG";"black";"no"
"100 DG";"100 DG black";"yes"
"100 DG";"silver 100 DG";"yes"
"100 DG";"silver 100 DG US edition";"yes"
...

所以,我想将结果写到第三列:

  • 如果包含,请写“是”
  • 如果未包含,请写“否”

我已经有一段时间没有做这种事情了,感谢您的帮助。

6 个答案:

答案 0 :(得分:1)

尝试一下:

#!/bin/bash
echo "\"PRODUCT\";\"VARIANT\";\"MATCH\""
tail -n +2 $1 | while read CSVLINE ; do
    AMATCH=$(echo $CSVLINE | awk -F\; '{ print $1 }' | tr -d '"')
    BMATCH=$(echo $CSVLINE | awk -F\; '{ print $2 }')
    TESTGREP=$(echo $BMATCH | grep "$AMATCH")
    if [[ $TESTGREP ]] ; then
        echo "\""$AMATCH"\";"$BMATCH";\"yes\""
    else
        echo "\""$AMATCH"\";"$BMATCH";\"no\""
    fi
done

示例(bash parse.sh file.csv):

root:~# bash parse.sh file.csv
"100 DG";"black";"no"
"100 DG";"100 DG black";"yes"
"100 DG";"silver 100 DG";"yes"
"100 DG";"silver 100 DG US edition";"yes"
root:~#

答案 1 :(得分:1)

这是awk的任务

#! /bin/sh

FILE=$1

sed -e "s/\"//g" < $FILE | awk -F\; '{
        if (index($2,$1)) {
                result="yes"
        } else {
                result="no"
        }
        printf("\"%s\";\"%s\";\"%s\"\n", $1, $2, result)
}'

首先使用sed摆脱所有\“的麻烦,在awk中轻松进行休息。 -F将字段分隔符设置为“;”,这对于CSV文件是有意义的。 然后使用AWK的字符串函数索引。 嵌入到Shell脚本中的AWK脚本非常强大。

用法:

shell$ bash report.sh data
"PRODUCT";"VARIANT";"no"
"100 DG";"black";"no"
"100 DG";"100 DG black";"yes"
"100 DG";"silver 100 DG";"yes"
"100 DG";"silver 100 DG US edition";"yes"

我喜欢这个变体,因为 a)它是良好的可读性和可维护性的代码 b)避免了必须启动其他一些Unix作业,因为所有事情都在一个AWK进程内处理(减少了cpu和i / o)

答案 2 :(得分:1)

与米勒(https://github.com/johnkerl/miller)是

mlr --csv --fs ";" put -S 'if ($VARIANT=~$PRODUCT) 
{$MATCH="yes"} 
    else 
{$MATCH="no"}' input_01.csv

或一行

mlr --csv --fs ";" put -S 'if ($VARIANT=~$PRODUCT) {$MATCH="yes"} else {$MATCH="no"}' input_01.csv

答案 3 :(得分:0)

这是为您提供的美丽的Perl单线纸:

cat file.csv | perl -pe '/"(.*?)";"(.*?");""/; ($2 =~ /$1/) ? s/""/"yes"/ : s/""/"no"/'

说明

/"(.*?)";"(.*?");""/;是一个正则表达式,它获取第1列(在$1处和第2列(在$2处)的值

($2 =~ /$1/)是一个条件,表示“列1是列2的子字符串”

然后我们有一个ternary operator,如果满足条件,则将输入字符串中的""替换为"yes",否则满足"no"

示例:

user@server:~$ cat file.csv | perl -pe '/"(.*?)";"(.*?");""/; ($2 =~ /$1/) ? s/""/"yes"/ : s/""/"no"/'
"PRODUCT";"VARIANT";"MATCH"
"100 DG";"black";"no"
"100 DG";"100 DG black";"yes"
"100 DG";"silver 100 DG";"yes"
"100 DG";"silver 100 DG US edition";"yes"

答案 4 :(得分:0)

另一种perl单线纸:

perl -i.back -ape '$.>1 && s/"(.+?)";"(?:(?!\1)[^"])*(\1)?.*?";"\K/${2}?"yes":"no"/e' file

其中:

-i.back     # replace file inplace but keep a backup with extension `.back`

正则表达式说明:

$.>1 &&     # if  line number greater than 1 (no change on first line)
s/          # substitute
  "(.+?)"   # capture the value of first column in group 1. 1 or more any character, not greedy
  ;"        # literally
  (?:       # start non capture group, tempered greedy token
    (?!\1)  # everything that is not the value contained in group 1 (i.e. the first column)
    [^"]    # 1 character that is not a double quote
  )*        # end group, may appear 0 or more time
  (\1)?     # group 2, same value as group 1, optional
  .*?       # 1 or more any character, not greedy
  ";"       # literally
  \K        # forget all we have seen until this position
/           # regex delim
  ${2}?     # does group 2 exist?
  "yes"     # it exits, change column 3 with "yes"
  :         # else
  "no"      # change column 3 with "yes"
/e          # end substitute, execute flag

输出:

"PRODUCT";"VARIANT";"MATCH"
"100 DG";"black";"no"
"100 DG";"100 DG black";"yes"
"100 DG";"silver 100 DG";"yes"
"100 DG";"silver 100 DG US edition";"yes"

答案 5 :(得分:0)

使用awk:

$ awk -F\; '{                               # set field separator
    v=$1                                    # duplicate $1 for ...
    gsub(/^"|"$/,"",v)                      # ... removing quotes
    print $0 ";\"" ($2~v?"yes":"no") "\""   # print appending yes or no
}' file

输出:

"PRODUCT";"VARIANT";"MATCH";"no"
"100 DG";"black";"";"no"
"100 DG";"100 DG black";"";"yes"
"100 DG";"silver 100 DG";"";"yes"
"100 DG";"silver 100 DG US edition";"";"yes"