我有文件1.csv
"word 1"
""
"word 3"
""
"word 5"
"word 6"
和文件2.csv
"replacement text 1"
"replacement text 2"
"replacement text 3"
"replacement text 4"
"replacement text 5"
"replacement text 6"
我正在寻找一个命令来检查 file1 中是否有空行(或带有“”的行),然后将其替换为 file2 的内容。
这输出.csv应该
"word 1"
"replacement text 2"
"word 3"
"replacement text 4"
"word 5"
"word 6"
答案1
假设这些文件具有相同的行数:用于paste
创建 CSV 记录流,其中第一个文件中的字段作为第一个无标题列,第二个文件中的字段作为第二个无标题列:
$ paste -d , file1.csv file2.csv
"word 1","replacement text 1"
"","replacement text 2"
"word 3","replacement text 3"
"","replacement text 4"
"word 5","replacement text 5"
"word 6","replacement text 6"
然后我们可以使用磨坊主如果第一个字段为空,则使用第二个字段的值更新第一个字段:
$ paste -d , file1.csv file2.csv| mlr --csv -N put 'is_empty($1) { $1 = $2 }'
word 1,replacement text 1
replacement text 2,replacement text 2
word 3,replacement text 3
replacement text 4,replacement text 4
word 5,replacement text 5
word 6,replacement text 6
对于任何空字段,测试is_empty()
都将为 true,无论输入中是否引用了该字段。
然后我们可以剪切(提取)第一个字段:
$ paste -d , file1.csv file2.csv| mlr --csv -N put 'is_empty($1) { $1 = $2 }' then cut -f 1
word 1
replacement text 2
word 3
replacement text 4
word 5
word 6
Miller 只会引用实际需要引用的字段。要强制 Miller 引用所有输出字段,请使用--quote-all
:
$ paste -d , file1.csv file2.csv| mlr --csv -N --quote-all put 'is_empty($1) { $1 = $2 }' then cut -f 1
"word 1"
"replacement text 2"
"word 3"
"replacement text 4"
"word 5"
"word 6"
您绝对可以使用 做类似的事情awk
,但请记住,它awk
不支持 CSV,会将双引号视为文字文本,因此会盲目地将每个逗号视为分隔符,即使它们嵌入在正确引用的字段中也是如此。它也不理解嵌入换行符的字段,但我们最初的假设已经排除了这些。
$ paste -d , file1.csv file2.csv| awk -F , '$1 == "\"\"" { $1 = $2 } { print $1 }'
"word 1"
"replacement text 2"
"word 3"
"replacement text 4"
"word 5"
"word 6"
答案2
另一种awk
选择:
awk '{getline other < "file2.csv"}
$0 == "\"\"" {$0 = other}
{print}' file1.csv > output.csv
或者paste
+ sed
:
paste -d '\n' file1.csv file2.csv| sed 'N;s/^""\n//;s/\n.*//' > output.csv
如果file2.csv
没有足够的行来满足, 与1""
的所有行,它将重用while 与+ 1 的最后一行,您将得到空行。如果行数多于 ,您还会在那里得到额外的空行。file1.csv
awk
file2.csv
paste
sed
file2.csv
file1.csv
答案3
$ awk -F, 'NR == FNR { a[FNR] = $1; next };
$1 == "\"\"" { $1 = a[FNR] };
1' file2.csv file1.csv
"word 1"
"replacement text 2"
"word 3"
"replacement text 4"
"word 5"
"word 6"
这将读取 file2.csv 并将每行的第 1 列存储在数组中。
然后读取 file1.csv,如果第 1 列只是一对双引号(即“空”),则将第一列替换为数组的适当元素(FNR
,或当前文件的当前行号)。然后它打印当前行,无论它是否已更改。
答案4
以下 Perl 脚本假定原始输入 ( file1.csv
) 是 stdin,并且替换文件作为命令行参数传递。
#!/usr/bin/perl
while (<STDIN>) {
$_ = <> if /^("")?$/;
print;
}
例如,以下任意一个:
$ cat file1.csv | perl this-script.pl file2.csv
$ <file1.csv | perl this-script.pl file2.csv
$ ./this-script.pl file2.csv <file1.csv
或者,作为单行:
$ perl -e 'while (<STDIN>) { $_ = <> if /^("")?$/; print }' <file1.csv file2.csv