Использование заглавных букв в верхнем регистре только первой буквы - PullRequest
0 голосов
/ 04 января 2019

В Perl есть функция ucfirst .

Это эквивалентно этому:

sub uppercase {     
    my ($W) = @_;       
    $$W = uc(substr($$W,0,1)).substr($$W,1);        
}

Имеет ли это значение в версии Perl?


Контекстуализируя вопрос, https://github.com/moses-smt/mosesdecoder/pull/206/files#diff-876e51db2a1ab71c1ae736182d1e5e04R63,

Ранее использование uppercase было таким:

sub process {
    my $line = $_[0];
    chomp($line);
    $line =~ s/^\s+//;
    $line =~ s/\s+$//;
    my @WORD  = split(/\s+/,$line);

    # uppercase at sentence start
    my $sentence_start = 1;
    for(my $i=0;$i<scalar(@WORD);$i++) {
      &uppercase(\$WORD[$i]) if $sentence_start;
      if (defined($SENTENCE_END{ $WORD[$i] })) { $sentence_start = 1; }
      elsif (!defined($DELAYED_SENTENCE_START{$WORD[$i] })) { $sentence_start = 0; }
    }

    # uppercase headlines {
    if (defined($SRC) && $HEADLINE[$sentence]) {
        foreach (@WORD) {
            &uppercase(\$_) unless $ALWAYS_LOWER{$_};
        }
    }

Но похоже, что замена &uppercase(\$WORD[$i]) и &uppercase(\$_) на ucfirst(\$WORD[$i]) и ucfirst(\$_) отличается.

Ответы [ 3 ]

0 голосов
/ 04 января 2019

ucfirst не эквивалентно следующему:

sub uppercase {     
    my ($W) = @_;       
    $$W = uc(substr($$W,0,1)).substr($$W,1);        
}

ucfirst в основном [1] эквивалентно следующему:

sub ucfirst {     
    my ($W) = @_;       
    return uc(substr($W,0,1)).substr($W,1);        
}

Если вы хотите переписать uppercase в терминах ucfirst, это будет выглядеть так:

sub uppercase {     
    my ($W) = @_;
    $$W = ucfirst($$W);    
}

uppercase(\$string);

Это означает, что если вы хотите полностью исключить uppercase, вы замените

uppercase(\$string);

с

$string = ucfirst($string);     # Correct

Вы пытались использовать

ucfirst(\$string);              # Wrong

  1. ucfirst на самом деле лучше справляется с обработкой более эзотерических символов, таких как U+ 01F3 ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО DZ ("dz"). ​​
0 голосов
/ 04 января 2019

Функции не эквивалентны из-за некоторых деталей Юникода, особенно в отношении орграфов .

Например, в венгерском языке используется орграф "DZ" ,которая считается одной буквой алфавита и поэтому может быть представлена ​​с помощью кодовых точек Unicode:

  • U+01F1: DZ
  • U+01F2: Dz
  • U+01F3: dz

Так что

my $text1 = "\x{1f3}won";
my $text2 = $text1;
$text1 = ucfirst($text1);
uppercase(\$text2);
print($text1 eq $text2 ? "same\n" : "different\n");

печатает "разные".

0 голосов
/ 04 января 2019

В Perl есть функция ucfirst.

Это эквивалентно этому:

Давайте выясним ...

$ cat testuc
use strict;
use warnings;
use Test::More; 

sub uppercase {
  my ($w) = @_;
  return uc(substr($w, 0, 1)) . substr($w, 1);
}

my @tests = qw[foobar Foobar FOOBar fOObar fOObAR FOOBAR];

for (@tests) {
  is(ucfirst($_), uppercase($_), "correct for $_");
}

done_testing;

$ prove -v testuc
testuc ..
ok 1 - correct for foobar
ok 2 - correct for Foobar
ok 3 - correct for FOOBar
ok 4 - correct for fOObar
ok 5 - correct for fOObAR
ok 6 - correct for FOOBAR
1..6
ok
All tests successful.
Files=1, Tests=6,  0 wallclock secs ( 0.04 usr  0.03 sys +  0.03 cusr  0.04 csys =  0.14 CPU)
Result: PASS

Итак, да, похоже, это одно и то же (по крайней мере, для моего довольно ограниченного набора тестов).

Я использую Perl 5.26.1 - но я думаю, что это будет хорошо работать длявсе версии Perl вернутся как минимум до 5.10.

Обновление:

Я сделал тихое редактирование вашего кода, которое я забыл упомянуть.Ваш код изначально работал со ссылкой на скаляр, но я изменил его для работы со скаляром ($W вместо $$W).Я предполагал, что это будет безвредной заменой.

Но теперь вы показали нам ваше изменение в контексте , и я могу видеть, что происходит.

У вас было:

&uppercase(\$WORD[$i])

И вы изменили это на:

ucfirst(\$WORD[$i])

Это не работает, так как ucfirst() не меняет свой аргумент;возвращает измененное значение.Таким образом, вы на самом деле хотите:

$WORD[$i] = ucfirst($WORD[$i]);

Это будет работать тогда, как и ожидалось (по модулю проблем с символами Unicode, упомянутыми в других ответах.

Весь ваш цикл может быть упрощен, если вы отойдете от Cстиль for петля.

for my $w (@WORD) {
  $w = ucfirst($w) if $sentence_start;

  if (defined $SENTENCE_END{ $w }) {
    $sentence_start = 1;
  } elsif (!defined $DELAYED_SENTENCE_START{ $w }) {
    $sentence_start = 0;
  }
}
...