我陷入了对SED来说应该很简单的事情。
我从其他应用程序获得了一些(某种)CSV文件,因此我无法控制其输出。一些预处理已经完成了SED,但是我被困在最后一个。所以我希望在可能的情况下使用SED来避免使用第三个应用程序。
问题是文件的标题行(第一行)沿着文件重复,但不幸的是具有以下特征:
所以,假设我有以下两个文件:
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
Check.processed.csv
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“保持缓冲区”作为删除命令的模式:
1h #Hold the first line (headings)
/\h/d #Use hold buffer as a pattern to delete
假设“\ h”将保持缓冲区返回到删除命令。
感谢您的回复;
PS:请不要回答以下过度具体的命令:
1p;/Name; Amount\|Name; Account; Amout/d
答案 0 :(得分:4)
我认为您需要从一个sed
命令中捕获第一行,然后在主操作命令中使用它:
line1=$(sed 1q $datafile)
sed -e "2,$ {/$line1/d;}" \
-e '...rest of sed script...' $datafile
因为sed 1q
在读取第一行后退出,所以无论数据文件有多大,它都会很快。如果第一行可能包含斜杠(可能是标题"Name/Number"
)或其他正则表达式元字符,那么请考虑使用类似的东西,用.
替换所有斜杠:
line1=$(sed '1{s%/%.%g;q;}' $datafile)
我使用Mac OS X(10.8.1)版本的sed
进行了一些操作,这比GNU sed
更加模糊。在第二个(主要)sed
命令中,匹配必须在{...}
中,美元必须是分开的(或者shell对无效参数替换感到厌倦),并且需要使用分号。 GNU sed
可能不需要其中一些限制,但显示的代码可能在任何地方都可以使用。
答案 1 :(得分:2)
这可能适合你(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脚本。
答案 2 :(得分:1)
如果您对awk感兴趣:
awk '{if(NR==1){p=$0;print}if(NR>1 && p!=$0)print}' your_file