Perl一线食谱:快速将列表转换为“用单引号引起的逗号分隔的字符串”或“多行”

时间:2019-02-03 09:41:32

标签: perl

问:如何快速,便捷地转换列表以进行进一步处理?

重点在于实现完全流畅的工作流程(无需麻烦地处理文件,管道,剪切和过去等)以进行进一步处理的通用方法。

Q1)将列表转换为单引号中逗号分隔的字符串

最需要在数据库(如MySQL,MariaDB,Oracle等)中插入值

A B C转换为'A','B','C'

第2季度:如何使用ID将ID列表转换为命令列表

由于缺乏外壳功能(例如,由于缺少外壳功能,因此大多数情况下需要重复使用具有多个进程号的单个命令)以终止Cisco路由器上的多个isakmp会话(VPN) (尽管可以使用Cisco IOS tclsh来实现-OS或Xargs)。

23828 11281 22873 3765 1234转换为

clear crypto isakmp 23828
clear crypto isakmp 22873
clear crypto isakmp 11281
clear crypto isakmp 22873
clear crypto isakmp  3765
clear crypto isakmp  1234

关于此问题的主要关注点

我完全了解SQL注入攻击的风险。但是,安全并不是这里的重点,因为我知道列表包含哪种数据。主要重点是采用一种通用的方法来即时转换列表,同时尽可能灵活。当然,使用诸如sed,awk,tr,cut或其他任何工具嗡嗡声之类的适当工具可以更好地完成某些任务。不幸的是,每次选择 best 工具来完成特定任务时,您都不得不弄弄语法,开关以及工具的工作方式。这正是我要避免使用更通用的方法的麻烦。

因此,请牢记以下主题:只需按一下击键即可调用 Perl单线,在执行之前,可以在shell中轻松地对其进行调整/编辑。我的方法-将我自己的答案和this作为一个副节点-完全满足此要求。 因此,在发布解决方案建议进行提问之前,最好先阅读我的答案。 ;-)

4 个答案:

答案 0 :(得分:0)

两者都可以快速且容易地使用短的perl一行程序完成。

A1:使用单引号将逗号分隔的字符串构建为一个字符串(即一行)

<强>首先创建下述(SQL)的例子中使用的列表:

cat > list.txt <<EOF
A
B
C
D
EOF

或者在Perl样式:

perl -le 'print foreach (A..D)' > list.txt

用单引号引起来的逗号分隔列表:

为了避免与bash的单引号解释相抵触,请对单引号<'>使用两位十六进制ASCII值 \ x27

perl -e 'print join ",", map { chomp; qq(\x27$_\x27) } <>' list.txt     # 'A','B','C','D'

同样的原理,只是用八进制ASCII值的 \ 047

 perl -e 'print join ",", map { chomp; qq(\047$_\047) } <>' list.txt    # 'A','B','C','D'
在需要双引号

有关其它目的(非SQL):

 perl -e 'print join ",", map { chomp; qq("$_") } <>' list.txt          # "A","B","C","D"

如果需要使用#;:作为分隔符,只需将,双引号内的join ",",替换为所需的内容

例如:
join "#",
join ";",
join ":",

在大多数情况下,列表是采取剪切和从其他地方粘贴。因此,在{em> Mac OS X上pbpaste的使用|的MacOS 可基本上缩短工作流程。顺便说一句:任何提示等效的Linux命令将不胜感激。要测试以下示例,请首先使用上面创建的列表填充剪贴板:cat list.txt | pbcopy

 pbpaste | perl -e 'print join ",", map { chomp; qq(\x27$_\x27) } <>'

更短;使用具有在飞行转化列表替换剪贴板的内容pbcopy

 pbpaste | perl -e 'print join ",", map { chomp; qq(\x27$_\x27) } <>' | pbcopy

为了在需要时使用它(例如,通过按 ctrl + x + c c进行转换),只需将此行写入$ HOME /。 inputrc

"\C-xc": "pbpaste | perl -e 'print join ",", map { chomp; qq(\x27$_\x27) } <>' | pbcopy"

激活键结合(见readline或许多问题标记,进一步):

 bind -f $HOME/.inputrc     # read/activate settings
 bind -s                    # show key-bindings

现在只需按 ctrl + x + c 即可自动转换您的SQL INSERT值。

:用于完整起见约SQL-引用

一些注解

Excerpt taken from this very good clarification about quotes and backticks单引号应用于VALUES()列表中的字符串值。 MySQL也支持字符串值使用双引号,但是单引号已被其他RDBMS广泛接受,因此使用单引号代替双引号是一个好习惯。

A2:从列表(例如,过程号)创建命令列表(即,多行)

与A1相比,此方法建立了多行(具有进程ID的命令重复)。

再次:首先创建一个列表,用于以下(Cisco)示例:

perl -le 'print foreach (1000..1010)' | pbcopy

实际上,将真实的进程ID复制到剪贴板;之后,将简单的数字列表转换为适当的命令列表:

pbpaste | perl -wle 'while (<>) {chomp; print "clear crypto isakmp $_"}'

这给出了:

clear crypto isakmp 1000
clear crypto isakmp 1001
clear crypto isakmp 1002
clear crypto isakmp 1003
clear crypto isakmp 1004
clear crypto isakmp 1005
clear crypto isakmp 1006
clear crypto isakmp 1007
clear crypto isakmp 1008
clear crypto isakmp 1009
clear crypto isakmp 1010

要在需要时也可以使用它(例如,按 ctrl + x + p p作为进程列表),只需将此行写入$ HOME /。 inputrc

"\C-xc": "pbpaste | perl -wle 'while (<>) {chomp; print "clear crypto isakmp $_"}' | pbcopy"

答案 1 :(得分:0)

该问题表明我们没有使用剪切粘贴等功能,因此我假设我们正在使用列表项并在Perl脚本中对其进行处理。

Q1提出了一种非常危险的方式来插入SQL。如果各个列表项恰好包含Perl认为不是特殊字符但SQL却认为特殊字符,则您已将数据库打开为injection attack

您应该在DBI层中创建一个prepared statement,而不是在Perl中合并列表,然后将列表项直接作为参数传递。

虽然可以正确清理列表中的元素,以避免在被视为SQL时被误解,但是使用预处理语句方法不太可能导致安全漏洞。

第二季度也是如此。尽管可以轻松地检查进程ID号,但通常情况下,最好直接传递参数,例如使用Perl的exec()或system()多参数形式。

答案 2 :(得分:0)

Q1)有2种方法。

$ echo "A B C" | perl -lpe ' s/(\S+)/\x27$1\x27/g ; s/\s+/,/g '
'A','B','C'

$ echo "A B C" | perl -ne ' @x=split(/\s+/); $_="\x27$_\x27" for(@x); print join(",",@x) '
'A','B','C'

第二季度

$ echo "23828 11281 22873 3765 1234" | perl -lane ' print "clear crypto isakmp $_" for(@F) '
clear crypto isakmp 23828
clear crypto isakmp 11281
clear crypto isakmp 22873
clear crypto isakmp 3765
clear crypto isakmp 1234

$

答案 3 :(得分:0)

您说您的第一个要求是“最需要在数据库中插入值”。您提出的解决方案对SQL injection attacks开放,应该避免。

为避免此问题,在将外部数据插入数据库时​​,应始终使用绑定点。像这样:

open my $fh, '<', 'somefile.txt' or die $!;

chomp(my @data = <$fh>);

my $sql = 'INSERT INTO some_table VALUES (';
$sql .= join ',', ('?') x @data;
$sql .= ')';

# Assume you already have a $dbh
my $sth = $dbh->prepare($sql);
$sth->execute(@data);

(当然,明确列出要向其中插入数据的列的名称始终是一个好习惯-为简单起见,在此省略了。)