我正在寻找一种方法来检查第一列(产品名称)的值是否存在于第二列(产品变体)和将结果(匹配/不匹配)写入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"
...
所以,我想将结果写到第三列:
我已经有一段时间没有做这种事情了,感谢您的帮助。
答案 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"