有没有人知道任何unix命令/ perl脚本会插入特定字符(可以输入为十六进制(即7C)或实际字符(即|))在第n次重复出现的位置具体人物。
即perl script.pl "," 3 "|" data.txt
将用管道替换每个第3,第6,第9 ......等逗号。
因此,如果在脚本运行之前data.txt有以下内容:
fd,3232,gfd67gf,
peas,989767,jkdfnfgjhf,
dhdhjsk,267,ujfdsy,fuyds,637296,ldosi,fduy,
873,fuisouyd,try
save,2837,ipoi
在脚本运行后应该有这个:
fd,3232,gfd67gf|
peas,989767,jkdfnfgjhf|
dhdhjsk,267,ujfdsy|fuyds,637296,ldosi|fduy,
873,fuisouyd|try
save,2837,ipoi
答案 0 :(得分:5)
小perl hack解决问题。使用index
函数查找逗号,模数替换正确的模数,使用substr
执行替换。
use strict;
use warnings;
while (<>) {
my $x=index($_,",");
my $i = 0;
while ($x != -1) {
$i++;
unless ($i % 3) {
$_ = substr($_,0,$x) ."|". substr($_,$x+1);
}
$x = index($_,",",$x + 1)
}
print;
}
使用perl script.pl file.csv
运行。
注意:您可以在my $i
循环之前放置声明while(<>)
以进行全局计数,而不是每行的单独计数。我不太清楚我在这方面理解你的问题。
答案 1 :(得分:3)
use File::Slurp qw(read_file);
my ($from, $to, $every, $fname) = @ARGV;
my $counter = 0;
my $in = read_file $fname;
my $out = $in;
# copy is important because pos magic attached to $in resets with substr
while ($in =~ /\Q$from/gms) {
$counter++;
substr $out, pos($in)-1, length($from), $to unless $counter % $every;
};
print $out;
如果$from
和$to
参数的长度不同,您仍然需要使用substr
的第二个参数进行混乱,以使其正常工作。
答案 2 :(得分:3)
一个漂亮,简单的awk
单行程怎么样?
awk -v RS=, '{ORS=(++i%3?",":"|");print}' file.csv
我刚刚遇到一个小错误:它将打印,
或|
作为最后一个字符。为避免这种情况,我们需要稍微改变一下:
awk -v RS=, '{ORS=(++i%3?",":"|");print}END{print ""}' file.csv | sed '$d'
答案 3 :(得分:1)
这一次处理输入文件一行(没有啜食:)
对于十六进制输入,只需传递'\x7C'
或其他任何内容,如$1
#!/bin/bash
b="${1:-,}" # the "before" field delimiter
n="${2:-3}" # the number of fields in a group
a="${3:-|}"; [[ $a == [\|] ]] && a='\|' # the "after" group delimiter
sed -nr "x;G; /(([^$b]+$b){$((n-1))}[^$b]+)$b/{s//\1$a/g}
s/.*\n//; h; /.*$a/{s///; x}; p" input_file
这里再次提出一些意见。
sed -nr "x;G # pat = hold + pat
/(([^$b]+$b){$((n-1))}[^$b]+)$b/{s//\1$a/g}
s/.*\n// # del fields from prev line
h # hold = mod*\n
/.*$a/{ s/// # pat = unmodified
x # hold = unmodified, pat = mod*\n
}
p # print line" input_file
答案 4 :(得分:1)
# Get params and create part of the regex.
my $delim = "\\" . shift;
my $n = shift;
my $repl = shift;
my $wild = '.*?';
my $pattern = ($wild . $delim) x ($n - 1);
# Slurp.
$/ = undef;
my $text = <>;
# Replace and print.
$text =~ s/($pattern$wild)$delim/$1$repl/sg;
print $text;
答案 5 :(得分:0)
我对bash脚本有一个想法:
perl -pe 's/,/(++$n % 3 == 0) ? "|" : $&/ge' data.txt
这样就可以了。