×

Loading...
Ad by
  • 最优利率和cashback可以申请特批,好信用好收入offer更好。请点链接扫码加微信咨询,Scotiabank -- Nick Zhang 6478812600。
Ad by
  • 最优利率和cashback可以申请特批,好信用好收入offer更好。请点链接扫码加微信咨询,Scotiabank -- Nick Zhang 6478812600。

我用的是Perl Script.

送给你一个函数Convert():
#!/usr/bin/perl
use strict;
my $tmp1='"asd ,asd", "123,345.78", "(12,345.67)","34"';
my $tmp2 = Convert($tmp1);
print "$tmp2\n";
exit(0);

sub Convert
{   my $intext = shift;
    return join(",", map { 
        if($_ =~ /[a-z]/) #chars
        {  $_ = '"'.$_.'"'
        }
        else #digits
        {   if( $_ =~ /^\(.+\)/ )
            {    $_ =~ s/[\(\)]//g;
                 $_ = '-'.$_;
            }
            $_ =~ s/,//g;
        }
        $_;
    }  grep(/./, split(/"\s*,*\s*"*/, $tmp1)));
}
Report

Replies, comments and Discussions:

  • 工作学习 / 专业技术讨论 / 那位能用最简单的方法将$tmp1='"asd ,asd", "123,345.78", "(12,345.67)","34"'; 转换成$tmp2="asd ,asd", 123345.78, -12345.67,34
    • sed 's/"(\(.*\))"/-\1/g' input.txt | sed 's/"\([0-9\.\,]*\)"/\1/g'
      • 数字中逗号没有去掉。
        • OK, how about this -> | sed 's/\([0-9]\)\,\([0-9]\)/\1\2/g'
          • All together:sed 's/"(\(.*\))"/-\1/g' tmp.txt | sed 's/"\([0-9\.\,]*\)"/\1/g' | sed "s/'\(.*\)';/\1/g" | sed 's/\([0-9]\)\,\([0-9]\)/\1\2/g' | sed 's/\$tmp1/\$tmp2/g'
            it's a stupid one, i know...
            • 还是不行,把最后一个‘,’去掉了。
              • Just adjust the sequence:sed 's/"(\(.*\))"/-\1/g' tmp.txt | sed 's/\([0-9]\)\,\([0-9]\)/\1\2/g' | sed 's/"\([0-9\.\,]*\)"/\1/g' | sed "s/'\(.*\)';/\1/g" | sed 's/\$tmp1/\$tmp2/g'
                • if tmp1 = "asd ,asd", "123,345.78", "(12,345.67)",34,45 and tmp2="asd ,asd", 123345.78, -12345.67,34,45; how to handle it?
    • 更正一下: # sed 's/"(\(.*\))"/-\1/g' tmp.txt | sed 's/"\([0-9\.\,]*\)"/\1/g' | sed "s/'\(.*\)';/\1/g"
    • 我用的是Perl Script.
      送给你一个函数Convert():
      #!/usr/bin/perl
      use strict;
      my $tmp1='"asd ,asd", "123,345.78", "(12,345.67)","34"';
      my $tmp2 = Convert($tmp1);
      print "$tmp2\n";
      exit(0);
      
      sub Convert
      {   my $intext = shift;
          return join(",", map { 
              if($_ =~ /[a-z]/) #chars
              {  $_ = '"'.$_.'"'
              }
              else #digits
              {   if( $_ =~ /^\(.+\)/ )
                  {    $_ =~ s/[\(\)]//g;
                       $_ = '-'.$_;
                  }
                  $_ =~ s/,//g;
              }
              $_;
          }  grep(/./, split(/"\s*,*\s*"*/, $tmp1)));
      }
      
      • 有点长
        • 但我认为是通用性最好的一个方案.
    • 强,轮胎大哥是正则高手
      • 轮胎大哥不止是正则高手:)
      • 轮胎大哥的思路是错误的
        • Oh? Y?
          • 正确的思路是找到你要的pattern, 然后进行修改,这个过程的难度在于要对pattern进行2步以上的修改,照你的思路,第一步完成后,你根本不可能再找回原来的pattern了
            • 我同意必须分两步匹配的观点,只能用perl来写,sed, awk好像 都作不到。
              • 和我的思路一样,我也只能用perl来写,不过用perl写得很短也很难。
        • 本猫不写正则好多年,看谁写的string最长就佩服谁,^_^
    • tmp1 换成tmp2干什么?
      • tmp1是从excel存下来,或是其他系统传来的数据,TMP2是需要的。
    • $_='"asd ,asd", "123,345.78", "(12,345.67)", "34"' and ( s/(\d{1})\,{1}(\d{1})/$1$2/g && s/\"{1}\(?([\d+\,\.]+)\)?\"{1}/$1/g && print ); # Perl
      • $_='"asd ,asd", "123,345.78", "(12,345.67)", "34"' and ( s/(\d{1})\,{1}(\d{1})/$1$2/g && s/\"{1}([\d+\.]+)\"{1}/$1/g && s/\"{1}\({1}([\d+\.]+)\){1}\"{1}/-$1/g && print ); # 以此为准
        • 我觉着你这个也行。
    • What about this:
      echo '"asd ,asd", "123,345.78", "(12,345.67)","34"' | perl -ne '(@a) = $_ =~ /("\w+\s+,\w+"),\s+"(.*)",\s+"\((.*)\)","(\d+)"/; map (s/(\d),/\1/, @a); print "$a[0], $a[1], - $a[2], $a[3]"'
      • 这个字符串的数字和字符位置在不同的文件会变化的,你这样基本上是hardcode了,意义不大
      • Oops, something is screwed up, try it again:
        echo '"asd ,asd", "123.345.78", "(12,345.67)","34"' | perl -ne ' (@a) = $_ =~ /("\w+\s+,\w+"),\s+"(.*)",\s+"\((.*)\)","(\d+)"/; map(s/(\d),/\1/,@a); print "$a[0], $a[1], - $a[2], $a[3]"'
        • 如果字符串换成"123,456.78","ert","45",453,你的还能用吗?
          • Well, then you have to let us know what exactly you want to do. Is that you want to remove all "," from digits or remove some of the quotes or what?
            • I may get you guys confused, sorry about that.
              when you got some input files with different numeric format, such as "12,345.78", "(2,345.23)", which come from excel, our system need a numeric format like 12345.78 and -2345.23, that's what I want to do, I can finish it by a piece of perl, I'd like to know some guys may finish it by sed, awk,...
        • Ok, for some reason all my escape "\" are gone after post, but you get the idea. Hard coded? hmmm....
          It should work for the pattern like "str, str","digits", "(digits)", "digits". all "," in the digits will be removed.
          • 要是这样,直接找第几个'"'再处理岂不是更简单吗?数字和自负的位置会经常变化的。
    • 我公布一下我的答案,我自己认为是目前最好的,不过我不会用awk,sed写出来
      my $tmp='"asd ,asd", "123,345.78", "(12,345.67)","34"'; $tmp =~ s/"\(?\d[\d,.]*\?)"/do{$a=$1;$a=~ s#,##g; if ($a =~s#\(|\)##g) {$a *= -1;}; $a/eg;
      • Ok, here we go again
        The way you asked is a bit confusing. But I think this one will do the trick:

        echo '"1,123,234.45", "(123,333.33)", "34.56", "dff, dfdf" ' |perl -ne 's/(\\d),(\\d)/\\1\\2/g && s/"\\((\\d.*)\\)"/-\\1/g && s/"(\\d)|(\\d)"/\\1\\2/g; print'

        (I doubled every escape char '\', just incase it gets stripped out)
        it gives you:
        1123234.45, -123333.33, 34.56, "dff, dfdf"
        • 这个真不错,我以前没有用过在两个 s///之间用&&,今天学习了一下,谢谢。
      • sed -e ':a;s/"\([0-9\.]*\)\,\([0-9\.\,]*\)"/"\1\2"/g;ta;:b;s/"(\([0-9\.]*\)\,\([0-9\.\,]*\))"/"(\1\2)"/g;tb;s/"(\(.*\))"/-\1/g;s/"\([0-9\.]*\)"/\1/g;s/tmp1/tmp2/g;' test.txt
        • ':-) make it advanced:';$a=sub { ...YOUR CODE && LOGIC HERE.. }; $_=$input && s/(".*?")/&$a($1)/ge && print;
        • if the string is "wer","1,123,234.45", TD,"(123,333.33)", "34.56", "dff, dfdf", your solution get failed too.
          • 你就不能一次把需求提完么...
          • sed -e ':a;s/"\([0-9\.]\+\)\,\([0-9\.\,]\+\)"/"\1\2"/g;ta;:b;s/"(\([0-9\.]\+\)\,\([0-9\.\,]\+\))"/"(\1\2)"/g;tb;s/"(\(.*\))"/-\1/g;s/"\([0-9\.]*\)"/\1/g;s/tmp1/tmp2/g;' test
            把*改成\+就结了.
            • 问题已经很清楚了,"(1,234.56)" => -1234.56, "234.56"=>234.56, 前两种也是一种表示数字的方法,我们需要的是后一种,你的表达还是不对,
              如果string="wer","1,123,234.45", TD,"(123,333.33)", "34.56", "dff, dfdf","(234)",你的还是不行。
              • 要修改很容易,只是你没有列出所有的可能性,我也懒得去一个一个的测.
                sed -e ':a;s/"\([0-9\.]\+\)\,\([0-9\.\,]\+\)"/"\1\2"/g;ta;:b;s/"(\([0-9\.]\+\)\,\([0-9\.\,]\+\))"/"(\1\2)"/g;tb;s/"(\([0-9\.]\+\))"/-\1/g;s/"\([0-9\.]*\)"/\1/g;s/tmp1/tmp2/g;' test
                • 算了。你好像根本没明白我们想干什么,这里面不存在"列出所有的可能性”这个文体。
    • 偶认为追求程序的长短不是很合理。假若你的任务很重要(如财务应用),那么你的程序应该尽量追求严谨和易维护(易读);假若你的任务需要高效率(如上百万纪录),那么你的程序应该尽量追求少占用系统资源(CPU和storage)。