Csv SED-删除文件其余部分中第一行出现的内容

Csv SED-删除文件其余部分中第一行出现的内容,csv,sed,text-files,Csv,Sed,Text Files,我被困在一些看起来应该很简单的事情中 我有一些CSV文件,我从另一个应用程序获得,所以我无法控制它的输出。SED已经完成了一些预处理,但我仍停留在最后一个。因此,如果可能的话,我希望使用SED来避免使用第三个应用程序 问题在于,文件第一行的标题行沿文件重复,但不幸的是,标题行具有以下特征: 每个CSV文件的标题以前是未知的。每个文件都有自己的标题,可能彼此不同; 不是每N行都会重复一次,因为N是一个固定的已知数字 其他数据非标题行可能会重复,并应予以维护 因此,假设我有以下两个文件: Cash.

我被困在一些看起来应该很简单的事情中

我有一些CSV文件,我从另一个应用程序获得,所以我无法控制它的输出。SED已经完成了一些预处理,但我仍停留在最后一个。因此,如果可能的话,我希望使用SED来避免使用第三个应用程序

问题在于,文件第一行的标题行沿文件重复,但不幸的是,标题行具有以下特征:

每个CSV文件的标题以前是未知的。每个文件都有自己的标题,可能彼此不同; 不是每N行都会重复一次,因为N是一个固定的已知数字 其他数据非标题行可能会重复,并应予以维护 因此,假设我有以下两个文件:

Cash.csv

Name; Amount
John; 3.55
Erick; 4.76
John; 8.99
Name; Amount
Erick; 4.76
Mark; 1.00
Name; Amount
John; 3.55
Check.csv

Name; Account; Amount
Erick; 345344; 123.00
Mark; 88849; 323.50
Name; Account; Amount
John; 474473; 99.00
Mark; 88849; 323.50
Mark; 88849; 323.50
John; 474473; 99.00
我所希望的是应用于每个文件的单个SED脚本将它们转换为:

Cash.processed.csv

Name; Amount
John; 3.55
Erick; 4.76
John; 8.99
Erick; 4.76
Mark; 1.00
John; 3.55
Name; Account; Amount
Erick; 345344; 123.00
Mark; 88849; 323.50
John; 474473; 99.00
Mark; 88849; 323.50
Mark; 88849; 323.50
John; 474473; 99.00
Check.processed.csv

Name; Amount
John; 3.55
Erick; 4.76
John; 8.99
Erick; 4.76
Mark; 1.00
John; 3.55
Name; Account; Amount
Erick; 345344; 123.00
Mark; 88849; 323.50
John; 474473; 99.00
Mark; 88849; 323.50
Mark; 88849; 323.50
John; 474473; 99.00
我想知道是否可以使用SED hold buffer作为delete命令的模式:

1h     #Hold the first line (headings)
/\h/d  #Use hold buffer as a pattern to delete
假设\h将保持缓冲区返回到delete命令

谢谢你的回复

PS:请不要用以下过于具体的命令回答:

1p;/Name; Amount\|Name; Account; Amout/d

我认为您需要从一个sed命令中捕获第一行,然后在主操作命令中使用它:

line1=$(sed 1q $datafile)

sed -e "2,$ {/$line1/d;}" \
    -e '...rest of sed script...' $datafile
因为sed 1q在读取第一行后退出,所以无论数据文件有多大,它都是快速的。如果第一行可能包含斜杠标题名称/编号,或者其他正则表达式元字符,那么可以考虑使用类似的方法,将所有斜杠替换为:


我用MacOSX10.8.1版的sed做了一些改进,它比GNUSED更复杂。在第二个主sed命令中,匹配必须在{…}中,美元必须分开,或者shell对无效的参数替换感到不安,并且需要分号。GNU sed可能不需要这些限制,但显示的代码可能在任何地方都可以使用。

我认为您需要从一个sed命令捕获第一行,然后在主操作命令中使用它:

line1=$(sed 1q $datafile)

sed -e "2,$ {/$line1/d;}" \
    -e '...rest of sed script...' $datafile
因为sed 1q在读取第一行后退出,所以无论数据文件有多大,它都是快速的。如果第一行可能包含斜杠标题名称/编号,或者其他正则表达式元字符,那么可以考虑使用类似的方法,将所有斜杠替换为:


我用MacOSX10.8.1版的sed做了一些改进,它比GNUSED更复杂。在第二个主sed命令中,匹配必须在{…}中,美元必须分开,或者shell对无效的参数替换感到不安,并且需要分号。GNU sed可能不需要这些限制,但显示的代码可能适用于任何地方。

这可能适用于GNU sed:

sed '1h;1!{G;/^\(.*\)\n\1/d;s/\n.*//}' file
说明:

1h将标题行存储在保留空间HS中并打印。 1.{G;/^\.\\n\1/d;s/\n.*/}对于除第一行以外的每一行,都附加一个新行,后跟HS的内容,即标题行。将行的第一部分与标题行进行比较,如果相同,则删除该行。如果不是,请删除附加的换行符和标题行,并按正常方式打印。 编辑:

这在大型文件上确实非常慢,一个更快、更容易理解的解决方案是:

sed 's|.*|1!{/^&$/d}|;q' file | sed -f - file

这将从输入文件的第一行生成sed脚本。

这可能适用于GNU sed:

sed '1h;1!{G;/^\(.*\)\n\1/d;s/\n.*//}' file
说明:

1h将标题行存储在保留空间HS中并打印。 1.{G;/^\.\\n\1/d;s/\n.*/}对于除第一行以外的每一行,都附加一个新行,后跟HS的内容,即标题行。将行的第一部分与标题行进行比较,如果相同,则删除该行。如果不是,请删除附加的换行符和标题行,并按正常方式打印。 编辑:

这在大型文件上确实非常慢,一个更快、更容易理解的解决方案是:

sed 's|.*|1!{/^&$/d}|;q' file | sed -f - file

这将从输入文件的第一行生成sed脚本。

如果您对awk感兴趣:

awk '{if(NR==1){p=$0;print}if(NR>1 && p!=$0)print}' your_file

如果您对awk感兴趣:

awk '{if(NR==1){p=$0;print}if(NR>1 && p!=$0)print}' your_file

+我也会这样做。如果第一行可能包含正则表达式元字符,则需要对它们进行转义。它的工作方式很有魅力,而且速度也很快。我花了大约0.5秒的时间制作了一个20MB的100万行文件。如果第一行可能包含正则表达式元字符,则需要对它们进行转义。它的工作方式很有魅力,而且速度也很快。对于一个20MB的100万行文件,我花了大约0.5秒的时间。或者更简单地说:NR==1{p=$0};NR==1 | | p!=$0.或者更简单地说,NR==1&&p=$0;p=$哇!小巧、快速、有力!我想我必须花一些时间来学习awk并重写我的HORE脚本;NR==1 | | p!=$0.或者更简单地说,NR==1&&p=$0;p=$哇!小的
,又快又有力!我想我得花点时间来学习awk和重写我的洞脚本。乔纳森,谢谢你的提示。还没有足够的声誉,但一旦我得到它,我会把它标记为有用的。我是一个长期只读堆栈溢出风扇。我没想到这么快就能得到有用的答案,所以现在我是一个超级超级超级粉丝。谢谢大家!!乔纳森,谢谢你的提示。还没有足够的声誉,但一旦我得到它,我会把它标记为有用的。我是一个长期只读堆栈溢出风扇。我没想到这么快就能得到有用的答案,所以现在我是一个超级超级超级粉丝。谢谢大家!!谢谢波通。对于小文件,我想这一行sed是最好的选择。但对于较大的文件,这可能会变得非常缓慢。我花了10秒来处理一个100万行的20MB文件,而Jonathan alternative用了0.5秒来处理。请参见已接受的答案。@RFVoltolini:您对结果的计时很有意思。Potong的sed表达式必须复制每一行,对其进行扩展,并在其上使用一个稍微复杂的正则表达式。正则表达式中的\1使其变得复杂,至少在执行它所需的时间内如此,然后通常删除对该行的扩展,因此它比简单的正则表达式匹配慢并不奇怪。不过,我有点惊讶,它的速度慢了20倍。不过,这是一个聪明的表达,波彤。谢谢波彤。对于小文件,我想这一行sed是最好的选择。但对于较大的文件,这可能会变得非常缓慢。我花了10秒来处理一个100万行的20MB文件,而Jonathan alternative用了0.5秒来处理。请参见已接受的答案。@RFVoltolini:您对结果的计时很有意思。Potong的sed表达式必须复制每一行,对其进行扩展,并在其上使用一个稍微复杂的正则表达式。正则表达式中的\1使其变得复杂,至少在执行它所需的时间内如此,然后通常删除对该行的扩展,因此它比简单的正则表达式匹配慢并不奇怪。不过,我有点惊讶,它的速度慢了20倍。不过,这是一个聪明的表达,波东。