Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 在输入中引用的CSV字段上保留引号_Perl_Csv - Fatal编程技术网

Perl 在输入中引用的CSV字段上保留引号

Perl 在输入中引用的CSV字段上保留引号,perl,csv,Perl,Csv,我有一个CSV文件,这样一些字段被引用,而不管它们是否需要被引用。我想做的是加载这个文件,修改一些值,并生成修改后的CSV,其中带引号的字段保持不变 我目前正在使用Perl的包试图解决这个问题,但遇到了一些障碍。以下是一个小测试脚本,用于演示该问题: use Text::CSV; my $csv = Text::CSV->new ({'binary' => 1, 'allow_loose_quotes' => 1, 'keep_meta_info' => 1}); my

我有一个CSV文件,这样一些字段被引用,而不管它们是否需要被引用。我想做的是加载这个文件,修改一些值,并生成修改后的CSV,其中带引号的字段保持不变

我目前正在使用Perl的包试图解决这个问题,但遇到了一些障碍。以下是一个小测试脚本,用于演示该问题:

use Text::CSV;

my $csv = Text::CSV->new ({'binary' => 1, 'allow_loose_quotes' => 1, 'keep_meta_info' => 1});
my $line = q^hello,"world"^;

print qq^input:  $line\n^;

$csv->parse($line);
my @flds = $csv->fields();
$csv->combine(@flds);

print 'output:  ', $csv->string(), "\n";
产生:

input:  hello,"world"
output:  hello,world
根据Text::CSV的文档,存在一个函数来测试输入中是否引用了字段,但是如果我使用它向字段添加周围的引号,我会得到意外的结果:

my $csv = Text::CSV->new ({'binary' => 1, 'allow_loose_quotes' => 1, 'keep_meta_info' => 1});
my $line = q^hello,"world"^;

print qq^input:  $line\n^;

$csv->parse($line);
my @flds = $csv->fields();

for my $idx (0..$#flds) {
    if ($csv->is_quoted($idx)) {
            $flds[$idx] = qq^"$flds[$idx]"^;
    }
}

$csv->combine(@flds);

print 'output:  ', $csv->string(), "\n";
制作:

input:  hello,"world"
output:  hello,"""world"""
我相信在
combine()
之前添加的引号会被视为字段的一部分,因此会在
combine()
正在处理时用第二个双引号转义


确保引用字段在输入到输出之间保持完整的最佳方法是什么?我不确定应用程序是否会接受
始终\u quote
'ed字段。。。是否存在允许保留引号完整的Text::CSV对象属性组合?或者也许我只剩下调整记录后的组合了?

这是一个遗憾,但似乎当
保留元数据信息
让您可以访问元数据时,没有选项告诉
文本::CSV
在输出时重新应用
被引用
状态

根据您的记录有多复杂,您可以自己重新组装它。但是,您必须处理对字符串字段的更改,这些更改以前是安全地不带引号的,但在处理之后现在需要带引号。这将取决于您引入的更改类型,即您是否期望以前的“安全”字符串值会变得不安全。如果答案是“从不”(即0.00000%的几率),那么您应该自己重新组装并记录您所做的工作

后期处理需要CSV解析字符串以处理字符串中可能存在的逗号和其他不安全字符,因此这可能不是一个选项

或者,您可以深入了解
Text::CSV
的代码,并实现所需的功能。即,允许用户在输出时强制引用特定字段。我对它进行了研究,看起来所需机制的一部分可能已经到位,但不幸的是,我只能访问XS版本,它将委托给本机代码,因此我现在无法深入研究。就我所知:

原始的
合并方法。注意将
\u FFLAGS
设置为
undef

sub combine
{
    my $self = shift;
    my $str  = "";
    $self->{_FIELDS} = \@_;
    $self->{_FFLAGS} = undef;
    $self->{_STATUS} = (@_ > 0) && $self->Combine (\$str, \@_, 0);
    $self->{_STRING} = \$str;
    $self->{_STATUS};
    } # combine
我的尝试。我猜想,
Combine
的第二个参数可能是标志,但由于(小写)
Combine
API基于接收数组而不是arrayref,因此无法传入两个数组。我将其更改为预期两个ArrayRef,并尝试将第二个ArrayRef传递给
Combine
,但由于“无法调用方法”print“on unblessed reference”而失败


+1个好问题,感谢您提供可运行的代码。
sub combine2
{
    my $self = shift;
    my $str  = "";
    my $f    = shift;
    my $g    = shift;
    $self->{_FIELDS} = $f;
    $self->{_FFLAGS} = $g;
    $self->{_STATUS} = (@$f > 0) && $self->Combine (\$str, $f, $g);
    $self->{_STRING} = \$str;
    $self->{_STATUS};
    } # combine