Perl从命令行脚本打印单引号

时间:2015-02-18 18:49:34

标签: bash perl

以下

echo text | perl -lnE 'say "word: $_\t$_"'

打印

word: text  text

我需要

word: 'text'    'text'

尝试:

echo text | perl -lnE 'say "word: \'$_\' \'$_\'";' #didn't works
echo text | perl -lnE 'say "word: '$_' '$_'";'     #neither

如何正确转义bash的单引号?

修改

想要准备一个包含几行mv行的shell脚本(用于检查,然后才真正重命名文件),例如尝试解决以下问题:

find . type f -print | \
perl \
  -MText::Unaccent::PurePerl=unac_string \
  -MUnicode::Normalize=NFC -CASD \
  -lanE 'BEGIN{$q=chr(39)}$o=$_;$_=unac_string(NFC($_));s/[{}()\[\]\s\|]+/_/g;say "mv $q$o$q $_"' >do_rename

e.g。来自文件名,如:

Somé filénamé ČŽ (1980) |Full |Movie| Streaming [360p] some.mp4

希望在文件do_rename

中获取以下输出
mv 'Somé filénamé ČŽ (1980) |Full |Movie| Streaming [360p] some.mp4' Some_filename_CZ_1980_Full_Movie_Streaming_360p_some.mp4

并且在手动检查后想要运行:

bash do_rename

用于运行实际重命名...

4 个答案:

答案 0 :(得分:3)

您可以使用:

echo text | perl -lnE "say \"word: '\$_'\t'\$_'\""
word: 'text'    'text'

BASH允许您在双引号中包含转义双引号,但同样不适用于单引号。但是,在执行此操作时,我们需要转义$以避免从BASH中逃脱。

答案 1 :(得分:3)

您可以为'使用ASCII代码39以避免逃脱地狱,

echo text | perl -lnE 'BEGIN{ $q=chr(39) } say "word: $q$_$q\t$q$_$q"'

答案 2 :(得分:2)

好的,根据您所遇到的问题陈述。我的建议是 - 不要管道找到perl,只是要求各种烦恼。

我并不完全熟悉这些模块,但建议您尝试这样的事情:

#!/usr/bin/perl

use strict;
use warnings;

use File::Find;
use Text::Unaccent::PurePerl qw ( unac_string ); 
use Unicode::Normalize qw ( NFC );
use Getopt::Std;
use File::Copy qw ( move );
use Encode qw(decode_utf8);

my %opts;
#x to execute, p to specify a path. 
#p mandatory. 
getopts('xp:',\%opts);


#this sub is called for each file, by the find function.
#$File::Find::name is the full path to the file.
#$_ is just the filename.     
sub rename_unicode_files {
   #skip if it's not a file. 
   next unless -f $File::Find::name;
   #convert name with functions from your example. 
   my $newname = unac_string(NFC(decode_utf8($File::Find::name)));
   $newname =~ s/[{}()\[\]\s\|]+/_/g;

   #could apply other transforms here, such as regular expressions. 

   #if the two names are different, consider moving. 
   unless ( $newname eq $File::Find::Name ) {
       print "Would rename: $File::Find::Name to $newname\n";

       #actually do it, if '-x' is specified. 
       if ( $opts{x} ) { move ( $File::Find::name, $newname ); };
   }
}

#require -p <pathname> or otherwise print how to use. 
unless ( -d $opts{p} ) { 
   print "Usage: $0 -p <pathname> [-x]\n";
   exit;
}

#trigger find with callback to subroutine, over the '-p <path>'. 
find ( \&rename_unicode_files, $opts{p} );

使用GetOpt::Std之类的内容进行扩展,以检查您是否指定了一个选项 - 这样您就可以正常运行,这就是我要做的事情&#39;如果你指定一个特定的标志,它实际上是这样做的。

使用perl内置renameFile::Copy

这将巧妙地避免您遇到的许多转义和插值问题,并且我认为通常会为您提供更具可读性和有用性的代码。

编辑:鉴于评论暗示上述内容太长&#39;怎么样:

#!/usr/bin/perl
use File::Find; use Text::Unaccent::PurePerl qw ( unac_string ); use Unicode::Normalize qw ( NFC ); find( sub { next unless -f $name; print "mv \'$File::Find::Name\' \'",unac_string( NFC($File::Find::name) )."\'\n"; }, "." );

仍然不相信这种方法的价值。即使它只是偶尔运行 - 更有理由让它尽可能清晰。

答案 3 :(得分:0)

有一个使用zsh shell和类SQL(至少是PostgreSQL和Oracle)引用风格的简单解决方案:

$ setopt rc_quotes
$ echo text | perl -lnE 'say "word: ''$_''\t''$_''"'
word: 'text'    'text'

要引用',只需将其加倍并在此模式下使用''