以下
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
用于运行实际重命名...
答案 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内置rename
或File::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'
要引用'
,只需将其加倍并在此模式下使用''
。