3

特定の文字のn番目の繰り返し出現の位置に特定の文字(16進数(つまり7C)または実際の文字(つまり|)として入力できます)を挿入するUNIXコマンド/Perlスクリプトを知っている人はいますか?つまり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
4

6 に答える 6

5

問題を解決するための小さなperlハック。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(<>)その点であなたの質問を理解したかどうかはよくわかりません。

于 2012-04-14T12:36:10.967 に答える
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は、の2番目のパラメータを少し混乱させる必要があります。substr

于 2012-04-14T12:39:40.950 に答える
3

素敵でシンプルなawkワンライナーはどうですか?

awk -v RS=, '{ORS=(++i%3?",":"|");print}' file.csv

小さなバグが1つ発生しました。それは、,または|を最後の文字として出力します。これを回避するには、少し変更する必要があります。

awk -v RS=, '{ORS=(++i%3?",":"|");print}END{print ""}' file.csv | sed '$d'
于 2012-04-14T15:16:43.543 に答える
1

これにより、入力ファイルが一度に1行ずつ処理されます(丸呑みはありません:) 。16進入力の場合は、次のよう
に渡す'\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
于 2012-04-14T15:00:37.957 に答える
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;
于 2012-04-14T16:11:23.673 に答える
1

私はbashスクリプトでアイデアを持っています:

perl -pe 's/,/(++$n % 3 == 0) ? "|" : $&/ge'  data.txt

それでうまくいきます。

于 2017-05-24T16:32:33.467 に答える