【问题标题】:How to print a string inside double quotes inside open brackets?如何在左括号内的双引号内打印字符串?
【发布时间】:2021-12-11 18:34:24
【问题描述】:
/* start of maker a_b.c[0] */

/* start of maker a_b.c[1] */

maker ( "a_b.c[0]" )

maker ( "a_b.c[1]" )

如何提取双引号内的字符串并将它们存储到数组中?这是我尝试过的。

open(file, "P2.txt");
@A = (<file>) ;
foreach $str(@A)
{
     if($str =~ /"a_b.c"/)
       {
           print "$str \n"; 
       } 
} 

注意:只有双引号内的内容必须存储到数组中。如果您在斜杠内看到示例的第一行,您将看到我想要匹配的相同字符串。那不应该被打印出来。所以只有双引号内的字符串应该存储到数组中。即使相同的字符串在没有双引号的情况下在其他地方重复,它也不应该被打印。 .

【问题讨论】:

  • 你能粘贴你试过的代码吗?
  • "您将能够在双引号中看到相同的字符串" 第一行的字符串周围没有双引号。您的意思是 not 在双引号中吗?目前你可以简单地做my @results = $str =~ /"(.*?)"/g;,对吧?
  • @vkk05 我已经展示了我所写的内容。请检查。
  • @Hakon 我的意思是同样提到的字符串也可以出现在双引号之外。所以我们应该只将提到的双引号中的字符串存储到数组中。
  • @BoggarapuLokesh 你必须打印@result 数组才能得到输出

标签: perl


【解决方案1】:

这不是寻找双引号中的字符串。它是关于定义一个模式(一个正则表达式)来匹配你想要找到的行。

为了使这项工作正常进行,我可以对您的代码进行最小的更改:

open(file, "P2.txt");
@A = (<file>) ;
foreach $str(@A)
{
     if($str =~ /"a_b.c/)  # <=== Change here
       {
           print "$str \n"; 
       } 
} 

我所做的只是从匹配表达式中删除结束双引号。因为你不关心之后会发生什么,所以你不需要在正则表达式中指定它。

我应该指出,这并不完全正确。在正则表达式中,点具有特殊含义(它的意思是“匹配此处的任何字符”),因此要匹配实际的点(这是您想要的),您需要使用反斜杠转义点。所以应该是:

if($str =~ /"a_b\.c/)

重写以使用一些更现代的 Perl 实践,我会这样做:

# Two safety nets to find problems in your code
use strict;
use warnings;

# say() is a better print()
use feature 'say';

# Use a variable for the filehandle (and declare it with 'my')
# Use three-arg version of open()
# Check return value from open() and die if it fails
open(my $file, '<', "P2.txt") or die $!;

# Read data directly from filehandle
while ($str = <$file>)
{
     if ($str =~ /"a_b\.c/)
       {
           say $str; 
       } 
}

您甚至可以使用隐式变量 ($_) 和语句修饰符来使您的循环更加简单。

while (<$file>) {
  say if /"a_b\.c/;
}

【讨论】:

    【解决方案2】:

    查看您提供的示例输入,该任务可以解释为“将单个字符串参数提取到看起来像函数调用的事物中”。似乎在 C 风格的 cmets 中存在不匹配的附加复杂性。为此,请注意perlfaq -q comment

    正如 FAQ 条目所示,忽略任意 C 样式 cmets 中的内容通常并非易事。我决定试试C::Tokenize 来帮忙:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use feature 'say';
    
    use C::Tokenize qw( tokenize );
    use Const::Fast qw( const );
    use Path::Tiny qw( path );
    
    sub is_open_paren {
        ($_[0]->{type} eq 'grammar') && ($_[0]->{grammar} eq '(');
    }
    
    sub is_close_paren {
        ($_[0]->{type} eq 'grammar') && ($_[0]->{grammar} eq ')');
    }
    
    sub is_comment {
        $_[0]->{type} eq 'comment';
    }
    
    sub is_string {
        $_[0]->{type} eq 'string';
    }
    
    sub is_word {
        $_[0]->{type} eq 'word';
    }
    
    sub find_single_string_args_in_invocations {
        my ($source) = @_;
    
        my $tokens = tokenize(path( $source )->slurp);
    
        for (my $i = 0; $i < @$tokens; ++$i) {
            next if is_comment( $tokens->[$i] );
    
            next unless is_word( $tokens->[$i] );
            next unless is_open_paren( $tokens->[$i + 1] );
            next unless is_string( $tokens->[$i + 2] );
            next unless is_close_paren( $tokens->[$i + 3]);
    
            say $tokens->[$i + 2]->{string};
            $i += 3;
        }
    }
    
    find_single_string_args_in_invocations($ARGV[0]);
    

    根据您的输入,产生:

    C:\Temp> perl t.pl test.c
    "a_b.c[0]"
    "a_b.c[1]"
    

    【讨论】:

      猜你喜欢
      • 2014-09-26
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多