微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我怎样才能让rubyShellWords.shellescape工作与多字节字符?

我一直在尝试调用一个包含来自Windows环境variables的多字节字符的参数,但是还没有find可行的解决scheme。 这是我至今能够debugging的东西。

为了简单起见,假定我有一个名为“Seán”的目录,我试图用它作为exec的一个参数。 如果我只是打电话

exec 'script',"Seu00E1n".encode("IBM437")

被执行的脚本找不到该文件,因为arg被调整为重音字符丢失。 如果我按照下面的方法进行操作,但是这样做是不好的做法,因为在进入shell之前,arg应该被转义。

exec "script #{"Seu00E1n".encode("IBM437")}"

所以我的想法是,我只是使用shellescape来保护exec的使用。

java控制台输出认字符编码

在C / C ++中检测string的编码

R,Windows和外语字符

在哪个Windows版本中,Windows ANSI Western(cp 1252)首次出现?

在Linux中将网页从UTF-8转换为ISO-8859-1

require 'shellwords' exec "script #{"Seu00E1n".encode("IBM437").shellescape}"

但问题是,它逃脱了特殊的性格,所以它看起来像下面这样 – “Se án”。 我想清楚这是在发生什么,它是从这个正则expression式来的 。

str.gsub!(/([^A-Za-z0-9_-.,:/@n])/,"\\\1")

乍看之下,似乎是逃避了已知的一组好的shell字符中的字符。 不幸的是,这套不包括特殊字符,所以我遇到了问题。

我正在寻找的是一个正则expression式,它会执行shell转义,不会混淆特殊字符,以便在将它们传递给exec之前可以将这些参数转义。

如何检测UTF8文本的等效Windows代码

将未知文件编码批量转换为UTF-8

我如何base64编码在Linux上的string,使其匹配窗口“Unicode.GetBytes.ToBase64String”?

换行从Linux到Windows的新行字符丢失

在Windows上,我无法使用cmd在我的数据库中看到utf8mb4字符

正则表达式/([^A-Za-z0-9_-.,:/@n])/只处理ASCII字母和数字,不是所有的Unicode字母。 [^...]是否定字符类 ,它匹配除了在类中指定的字符以外的所有字符。 所以,所有的Я , Ц , Ą都被删除,因为它们与[A-Za-z]不匹配。

你需要的是添加速记类来排除所有的Unicode字母和数字 。 为了使它更安全,我们可以添加一个变音符号类以便保留变音符号:

str.gsub(/([^p{L}p{M}p{N}_.,:/@n-])/,"\\\1")

在这里, p{L}匹配所有Unicode基本字母, p{M}匹配所有的变音符号, p{N}匹配任何Unicode数字。

请注意,连字符在放置在字符类的开始/结尾处(或在有效范围或简写字符类之后)时无需转义。

TL; DR

转义字符

String.class_eval do def escapeshell() # Escape shell special characters self.gsub!(/[#-&(-*;<>?[-^`{-~u00FF]/,'\\') # Escape unbalanced quotes (single and double quotes) self.gsub!(/(["'])(?:([^"']*(?:(?!1)["'][^"']*)*)1)?/) do if $2.nil? '\' + $1 else # and escape quotes inside (eg "x'x" or 'y"y') qt = $1 qt + $2.gsub(/["']/,'\\') + qt end end self end end # Test it str = "(dir *.txt & dir "\some dir\Sèu00E1ñ*.rb") | sort /R >Filé.txt 2>&1" puts 'String:' puts str puts "nescaped:" puts str.escapeshell

产量

String: (dir *.txt & dir "some dirsèáñ*.rb") | sort /R >Filé.txt 2>&1 Escaped: (dir *.txt & dir "\some dir\Sèáñ*.rb") | sort /R >Filé.txt 2>&1

ideone演示

描述

元字符

考虑到应该转义的shell元字符:

# & % ; ` | * ? ~ < > ^ ( ) [ ] { } $ u00FF

我们可以在字符类中包含每个字符:

[#&%;`|*?~<>^()[]{}$\u00FF]

这与以下内容完全相同:

/[#-&(-*;<>?[-^`{-~u00FF]/

然后,我们使用gsub!()在类中的任何字符之前加上一个反斜杠:

str.gsub!(/[#-&(-*;<>?[-^`{-~u00FF]/,'\\')

行情

只有不平衡的引号需要逃脱。 这对保存命令的参数非常重要。 用下面的表达式我们匹配平衡的引号:

/(["'])[^"']*(?:(?!1)["'][^"']*)*)1/

以及不平衡,使最后一部分可选

/(["'])(?:[^"']*(?:(?!1)["'][^"']*)*)1)?/

但是我们也需要在另一对里面逃避报价。 这是双引号内的单引号,反之亦然。 所以我们将嵌套另一个gsub()来替换引号( $2 )中匹配的文本:

str.gsub!(/(["'])(?:([^"']*(?:(?!1)["'][^"']*)*)1)?/) do if $2.nil? '\' + $1 else qt = $1 qt + $2.gsub(/["']/,'\\') + qt end end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐