Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在CSV中查找字符串的一部分并用新条目替换整个单元格?_Python_Bash_Csv_Awk_Sed - Fatal编程技术网

Python 在CSV中查找字符串的一部分并用新条目替换整个单元格?

Python 在CSV中查找字符串的一部分并用新条目替换整个单元格?,python,bash,csv,awk,sed,Python,Bash,Csv,Awk,Sed,我有一个CSV文件,其中有一列我想筛选。我想使用一个模式文件来查找模式存在的所有条目,甚至是列值的一部分,并用这个“模式”替换整个单元格值。 我列出了一个我想用作“模式”库的关键字列表; 因此,如果此列中的一个单元格(本例仅为第二个)将此“模式”作为其字符串的一部分,那么我想用此“模式”替换整个单元格 例如: 我的目标文件: id1,Taxidermy Equipment & Supplies,moreinfo1 id2,Taxis & Private Hire,moreinfo

我有一个CSV文件,其中有一列我想筛选。我想使用一个模式文件来查找模式存在的所有条目,甚至是列值的一部分,并用这个“模式”替换整个单元格值。 我列出了一个我想用作“模式”库的关键字列表; 因此,如果此列中的一个单元格(本例仅为第二个)将此“模式”作为其字符串的一部分,那么我想用此“模式”替换整个单元格

例如:

我的目标文件:

id1,Taxidermy Equipment & Supplies,moreinfo1
id2,Taxis & Private Hire,moreinfo2
id3,Tax Services,moreinfo3
id4,Tools & Hardware,moreinfo4
id5,Tool Sharpening,moreinfo5
id6,Tool Shops,moreinfo6
id7,Video Conferencing,moreinfo7
id8,Video & DVD Shops,moreinfo8
id9,Woodworking Equipment & Supplies,moreinfo9
我的“模式”文件:

输出文件:

id1,Taxidermy Equipment & Supplies,moreinfo1
id2,Taxis,moreinfo2
id3,Tax Services,moreinfo3
id4,Tool,moreinfo4
id5,Tool,moreinfo5
id6,Tool,moreinfo6
id7,Video,moreinfo7
id8,Video,moreinfo8
id9,Wood,moreinfo9
我想出了通常的“查找并替换”sed:

但我想让它在特定的专栏上运行,所以我想到:

awk 'BEGIN{OFS=FS="|"}$2==PATTERN{$2=REPLACE}{print}' file.csv
但它在“字符串的一部分”([视频]:“视频和DVD商店”->“视频”)上不起作用,我似乎无法理解awk如何将输入作为“模式”块的文件

有一个awk脚本吗?或者我必须编写一些东西(例如,使用内置csv套装的python?

Perl解决方案,使用:

#/usr/bin/perl
使用警告;
严格使用;
使用Text::CSV_XS qw{CSV};
my($input\u file,$pattern\u file)=@ARGV;
打开我的$pfh,“这里有一个(大部分)awk解决方案:

#/bin/bash

patterns_regex=`cat patterns_file  | tr '\n' '|'`
cat target_file | awk -F"," -v patterns="$patterns_regex" '
BEGIN {
    OFS=",";
    split(patterns, patterns_split, "|");
}

{
    for (pattern_num in patterns_split) {
        pattern=patterns_split[pattern_num];
        if (pattern != "" && $2 ~ pattern) {
            print $1,pattern,$3
        }
    }
}'

在awk中,使用
索引
。它仅在进行替换时打印记录,但即使没有匹配项,也很容易修改为打印(例如,将
print$1,i,$3}
替换为
$0=$1 of s i of s$3}1
):


当您想用
sed
解决这个问题时,您需要一些步骤。
对于每个模式,都需要一个命令,如

sed 's/^\([^,]*\),\(.*Tool.*\),/\1,Tool,/' inputfile
您将需要每个图案两次,您可以使用

sed 's/.*/"&" "&"/' patternfile
# Change the / into #, thats easier for the final command
sed 's#.*#"&" "&"#' patternfile
当您指示sed读取命令文件时,确实需要以
sed
开始每一行。命令文件看起来像

sed 's#.*#s/^\\([^,]*\\),\\(.*&.*\\),/\\1,&,/#;s#&#\\&#g'  patternfile
您可以存储这是一个文件并使用该文件,但通过进程替换,您可以执行以下操作

cat <(echo "Now this line from echo is handled as a file")

您可以在awk中完成,不管它是什么,但是您忽略了有趣/难以处理的用例,即如果两个“模式”匹配目标字段,或者如果存在部分匹配而不是整个单词匹配(例如Tax on Taxi),或者如果一个“模式”是另一个“模式”或“模式”的子字符串,那么您希望发生什么包含regexp元字符,或者如果它包含反向引用,或者……我想我正在筛选一大堆数据,所以只要我能充分利用这些数据,一些异常就不会困扰我。无论如何,谢谢你的留言!非常感谢,我已经有一段时间没有使用perl脚本了——但我想有时候我不得不坐下来研究它——为什么现在不呢!非常感谢你的解释,这正是我一直在寻找的AWK,我甚至从中学到了一些东西!嘿,由于没有过滤我的模式,我遇到了麻烦,所以我决定将模式文件制作成两列csv。第一列是要搜索的内容,第二列是要打印的内容。我厌倦了在脚本上乱搞,但我不能强迫它使用这个“数组”,它会抱怨“我”是一个标量。你有没有可能再看看这个?我想我该“拆分”我的新模式文件了,不是吗?你应该提出一个新问题,并用它发布新的示例文件。嘿,谢谢你的快速回复,但我已经弄明白了。对于那些可能觉得这很有用的人,下面是我的窍门:awk'BEGIN{FS=OFS=“,”}FNR==NR{split($0,f,/:/)map[f[1]]=f[2]next}{For(i=2;我希望能有一个冗长的解释!我从来没有深入研究过sed,应该在周末的某个时候认真研究一下。
sed 's/^\([^,]*\),\(.*Tool.*\),/\1,Tool,/' inputfile
sed 's/.*/"&" "&"/' patternfile
# Change the / into #, thats easier for the final command
sed 's#.*#"&" "&"#' patternfile
sed 's#.*#s/^\\([^,]*\\),\\(.*&.*\\),/\\1,&,/#;s#&#\\&#g'  patternfile
cat <(echo "Now this line from echo is handled as a file")
sed -f <(sed 's#.*#s/^\\([^,]*\\),\\(.*&.*\\),/\\1,&,/#'  patternfile) inputfile
sed -f <(sed 's#.*#s/^\\([^,]*\\),\\(.*&.*\\),/\\1,&,/#;s#&#\\&#g' patternfile) inputfile