【问题标题】:Perl CGI script reads text file content with backslash incorrectlyPerl CGI 脚本错误地读取带有反斜杠的文本文件内容
【发布时间】:2020-06-19 11:23:18
【问题描述】:

我有一个包含反斜杠 (\something) 的行的简单文本文件。在命令行上的 Perl 脚本中读取它时,我得到的文本行与文件中的文本行完全相同。当将完全相同的代码行复制并粘贴到 CGI 脚本中时,通过为每个反斜杠添加一个反斜杠来以不同方式读取文本文件内容。我花了两天时间搜索各种论坛(StackOverflow、PerlMonks 等),但找不到可能的原因。下面是代码和文本文件。非常感谢任何帮助。

**~/tests/backslash> cat /home/user1/tests/backslash/pattern.txt**
more LaTex formatted strings.
\frac{a}{b} = \frac{5}{7}
**~/tests/backslash>  cat test.pl**
my $file = "/home/user1/tests/backslash/pattern.txt";
print STDERR "Attempting to open $file and read the last line...\n";
open(FH, "< $file") or die "ERROR: can't open $file: $!";
my @lines = <FH>;
close(FH);
my $myExpression = $lines[scalar(@lines) - 1];
chomp($myExpression);
print STDERR 'Expr: [' . $myExpression . "]\n";
my $retString = qq{{ "result" : "$myExpression" }};
print STDERR $retString . "\n";
**~/tests/backslash> ./test.pl**
Attempting to open /home/user1/tests/backslash/pattern.txt and read the last line...
Expr: [\frac{a}{b} = \frac{5}{7}]
{ "result" : "\frac{a}{b} = \frac{5}{7}" }
**~/tests/backslash>**

CGI 脚本中完全相同的代码产生以下输出:

我将字符串拆分为数组并检查了每个字符(在 CGI 脚本中),它在“frac”之前有两个反斜杠。 Dumper 也证实了这一点。我试图用'\'替换两个反斜杠,但也没有成功。我在理解和解决这个问题时遇到了许多其他问题(例如,CGI 脚本无法从 /tmp[file not found] 打开相同的文本文件,用 \ 替换两个反斜杠以各种方式失败并出现语法错误,变量值越来越替换时出现意外字符等,但我关注的是这个问题中反斜杠的核心问题。)我在命令行脚本和 CGI​​ 脚本中使所有“使用”类完全相同,以防万一,即使命令行脚本不使用 CGI、JSON 等。

我很困惑为什么完全相同的 Perl 代码在 cgi-bin 中的行为不同。对此的任何帮助、建议、指示或讨论表示赞赏。

My environment:
Suse Linux 13.1
Perl 5.18.1
Apache 2.4.6
Bash 4.2.53

【问题讨论】:

  • Dumper 是如何确认这一点的? Dumper 输出转义反斜杠和单引号,因此 Dumper 输出中的双反斜杠并不意味着输入中的双反斜杠。试试perl -MData::Dumper -e 'print Dumper(q/123\456/)'
  • 我认为您正在查看的只是日志输出有反斜杠转义,并且脚本没有做任何不同的事情。
  • mob,你是对的,Dumper 正在转义反斜杠。但我尝试了 'my @charArr = split('', $expr);并打印每个字符。此外,为了以防 PRINT 和 Dumper 正在转义字符,我尝试进行比较 ($charArr[i] eq q|\\|) ,它的反斜杠标记的计算结果为 true。为了防止 Perl 插入 q|\\|,我什至尝试在 'here' 文档中制作一个反斜杠作为模式并进行比较,结果仍然确认了两个反斜杠。
  • 顺便说一句,我只是将字符串原样返回给网页上的调用 Ajax 函数(内容类型:application/json),并在那里看到两个反斜杠。
  • JSON 编码也将转义输入中的反斜杠。 JSON 输出中的两个反斜杠意味着输入中的一个反斜杠。 . . . perl -MJSON -e 'print JSON::encode_json([q/123\456/])'

标签: file perl escaping cgi backslash


【解决方案1】:

请看下面的编码风格是否更合适

use strict;
use warnings;
use feature 'say';

my $file = '/home/user1/tests/backslash/pattern.txt';

say STDERR "Attempting to open $file and read the last line...";

open my $fh, '<',  $file
    or die "ERROR: can't open $file: $!";

my @lines = <$fh>;

close(FH);

my $myExpression = pop @lines;

chomp($myExpression);

say STDERR "Expr: [$myExpression]";

my $retString = qq{{ "result" : "$myExpression" }};

say STDERR $retString;

注意: perl 有运算符 pop 来提取数组的最后一个元素

注意:双引号字符串假定变量​​插值,应该相应地使用它——如果字符串中没有变量,那么可能双引号放错了

注意:免费书籍Modern Perl 可在线获取——参见“输入和输出”第 138 页

注意: use strict; use warnings 可以避免许多陷阱

【讨论】:

  • 谢谢。我使用了严格、警告、诊断和其他一些。这是使用语句的列表。 使用严格;使用警告;使用 utf8;使用致命 qw/:void open close/;使用 JSON;使用 CGI;使用 CGI::Carp qw(fatalsToBrowser);使用 Data::Dumper;使用配置::常规;使用 POSIX qw/strftime/;使用 String::ShellQuote qw(shell_quote);使用 File::Basename;使用 File::Path qw(make_path);;使用 Time::HiRes qw(gettimeofday);
【解决方案2】:

我想我找到了问题所在。它在 MathJax 中接受 LaTex 字符串并进行渲染。它一直用反斜杠渲染字符串,所以我追溯了双反斜杠的来源,最终在 http 日志中找到了它们。对文件的任何打印也会导致转义。在命令行上运行的脚本会将其打印到终端,因此反斜杠不会被转义。在 cgi-bin 中运行时,没有转义就无法看到实际的字符串。将字符串拆分为数组并单独打印字符没有区别。数组元素与引用的 q|\| 的比较也受到转义/插值。因此,我无法以任何其他方式验证这一点。最后,在修复了 MathJax 的配置后,它正确地呈现了字符串。我留下这个问题并回答希望它能为某人节省一些时间。感谢大家阅读、评论和回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2011-08-02
    • 2012-08-20
    • 2018-11-21
    相关资源
    最近更新 更多