如何使用 perl “应用”退格字符
How to “apply” backspace characters with perl
我有一个包含多个退格字符 (^H
) 的文件。我希望能够 "apply" perl 中的那些退格键。我找到了一些解决方案,但其中 none 对我有效。
关键是这条线:
test>>M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M
结果应如下所示:
test>>Management.Files.scripts.show_file = transform_factory_to_running^M
在 vi 中,我能够按照 中的建议正确转换文本。
但是这个问题中也提出了 perl 解决方案: didn't work for me (using $_
):
s{([^\x08]+)(\x08+)}{substr,0,-length}eg;
这个输出是:
test>>Management.Files.sscriptriptscripts.show_file = transform_factory_to_running^M
所有退格键都消失了,但看起来好像其中一些退格键被应用到另一个退格键?!
这是一个可能不是最快的非常明确的解决方案。但是,它完成了工作。
sub apply_backspace_characters {
my $string = shift;
# replace the ^H characters with one BS char
$string =~ s/\^H/chr(8)/ge;
my @output;
my $backspace_count = 0; # keep track of how many BS we have seen in a row
# iterate over string by char from the right
foreach my $char ( reverse split //, $string ) {
if ( $char eq chr(8) ) {
# it's a backspace, increase counter and skip
$backspace_count++;
next;
}
if ($backspace_count) {
# there are still backspaces on the 'stack', decrease counter and skip
$backspace_count--;
next;
}
# no backspaces left, keep this character and put at front
# (because we are going backwards)
unshift @output, $char;
}
return join '', @output;
}
say apply_backspace_characters(
"test>>M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M"
);
这将输出以下内容。
test>>Management.Files.scripts.show_file = transform_factory_to_running^M
这只是在替换循环中完成的
它重复删除行首的所有退格键实例(此处无效)或后跟退格键的非退格键(模拟删除前面的字符)
请注意,我不得不在正则表达式模式中使用 \cH
而不是 \b
,因为后者在这种情况下是词边界锚
use strict;
use warnings;
use v5.10;
my $s = 'M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M';
$s =~ s/\^H/\b/g; # convert `^H` to backspace
1 while $s =~ s/(?:^|[^\cH])\cH//g;
say $s;
产出
Management.Files.scripts.show_file = transform_factory_to_running^M
更新
这是一个将字符串作为字符流处理的版本,类似于 simbabque's 解决方案,但从左到右
基本上任何退格键都会从 $result
缓冲区的末尾删除一个字符,如果有一个字符要删除,而任何其他字符只是附加
输出与上面的代码相同
use strict;
use warnings;
use v5.10;
my $s = 'M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M';
$s =~ s/\^H/\b/g;
say apply_backspace_characters($s);
sub apply_backspace_characters {
my $result;
for my $c ( split //, shift ) {
if ( $c eq "\b" ) {
substr($result, -1) = '';
}
else {
$result .= $c;
}
}
$result;
}
我有一个包含多个退格字符 (^H
) 的文件。我希望能够 "apply" perl 中的那些退格键。我找到了一些解决方案,但其中 none 对我有效。
关键是这条线:
test>>M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M
结果应如下所示:
test>>Management.Files.scripts.show_file = transform_factory_to_running^M
在 vi 中,我能够按照 中的建议正确转换文本。
但是这个问题中也提出了 perl 解决方案: didn't work for me (using $_
):
s{([^\x08]+)(\x08+)}{substr,0,-length}eg;
这个输出是:
test>>Management.Files.sscriptriptscripts.show_file = transform_factory_to_running^M
所有退格键都消失了,但看起来好像其中一些退格键被应用到另一个退格键?!
这是一个可能不是最快的非常明确的解决方案。但是,它完成了工作。
sub apply_backspace_characters {
my $string = shift;
# replace the ^H characters with one BS char
$string =~ s/\^H/chr(8)/ge;
my @output;
my $backspace_count = 0; # keep track of how many BS we have seen in a row
# iterate over string by char from the right
foreach my $char ( reverse split //, $string ) {
if ( $char eq chr(8) ) {
# it's a backspace, increase counter and skip
$backspace_count++;
next;
}
if ($backspace_count) {
# there are still backspaces on the 'stack', decrease counter and skip
$backspace_count--;
next;
}
# no backspaces left, keep this character and put at front
# (because we are going backwards)
unshift @output, $char;
}
return join '', @output;
}
say apply_backspace_characters(
"test>>M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M"
);
这将输出以下内容。
test>>Management.Files.scripts.show_file = transform_factory_to_running^M
这只是在替换循环中完成的
它重复删除行首的所有退格键实例(此处无效)或后跟退格键的非退格键(模拟删除前面的字符)
请注意,我不得不在正则表达式模式中使用 \cH
而不是 \b
,因为后者在这种情况下是词边界锚
use strict;
use warnings;
use v5.10;
my $s = 'M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M';
$s =~ s/\^H/\b/g; # convert `^H` to backspace
1 while $s =~ s/(?:^|[^\cH])\cH//g;
say $s;
产出
Management.Files.scripts.show_file = transform_factory_to_running^M
更新
这是一个将字符串作为字符流处理的版本,类似于 simbabque's 解决方案,但从左到右
基本上任何退格键都会从 $result
缓冲区的末尾删除一个字符,如果有一个字符要删除,而任何其他字符只是附加
输出与上面的代码相同
use strict;
use warnings;
use v5.10;
my $s = 'M^H ^HManagement.^H^H^H^H^H^H^H^H^H^Hanagement.F^H ^HFiles.^H^H^H^H^Hiles.s^H ^Hs.^H ^Hc^H ^H^H ^Hscript.^H ^H^H^H^H^Hripts^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^Hscripts.^H.s^H ^Hshow_file ^H^H^H^H^H^H^H^H^Hhow_file = transform_factory_to_running^M';
$s =~ s/\^H/\b/g;
say apply_backspace_characters($s);
sub apply_backspace_characters {
my $result;
for my $c ( split //, shift ) {
if ( $c eq "\b" ) {
substr($result, -1) = '';
}
else {
$result .= $c;
}
}
$result;
}