Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex BASH使用ñ;名义上_Regex_Bash_Find_Quoting - Fatal编程技术网

Regex BASH使用ñ;名义上

Regex BASH使用ñ;名义上,regex,bash,find,quoting,Regex,Bash,Find,Quoting,已经尝试了多种解决方案,但似乎都不起作用 例如,如果我尝试下一个命令,它将按预期工作 find . -type f -name *x* 它返回: ./alphabet/output/b/box.jpg /字母表/输出/t/taxi.jpg 但是,如果我尝试使用西班牙语字母表中的任何特殊字符,该命令将不起作用 find . -type f -name *ñ* 结果是空的 如果我尝试 find . -type f -name *n* 然后它还会显示带有特殊字符ñ的文件名 如果我试图为命令设置L

已经尝试了多种解决方案,但似乎都不起作用

例如,如果我尝试下一个命令,它将按预期工作

find . -type f -name *x*
它返回:

./alphabet/output/b/box.jpg

/字母表/输出/t/taxi.jpg

但是,如果我尝试使用西班牙语字母表中的任何特殊字符,该命令将不起作用

find . -type f -name *ñ*
结果是空的

如果我尝试

find . -type f -name *n*
然后它还会显示带有特殊字符ñ的文件名

如果我试图为命令设置LANG变量,它也不起作用

LANG=C find . -type f -name *ñ*
还是用正则表达式

LANG=C find . -type f -name *.jpg -regex '.*[ñ].*'
(其中一部分是从一家公司偷来的。)

Unicode允许以几种不同的方式表示某些重音字符:作为表示重音字符的“代码点”,或作为表示字符的非重音版本的一系列代码点,后跟重音。例如,“ñ”可以表示为预合成为U+00F1(UTF-8 0xc3b1,带波浪号的拉丁文小写字母n)或分解为U+006E U+0303(UTF-8 0x6ecc83,带波浪号的拉丁文小写字母n+)

OSX的HFS+文件系统要求所有文件名都以其完全分解形式的UTF-8表示形式存储(少数例外情况与此无关)。在HFS+文件名中,“ñ”必须编码为0x6ecc83

当您在键盘上键入“ñ”时,它使用组合形式U+00F1(0xc3b1)。您可以通过十六进制转储看到这一点:

$ echo ñ | xxd
00000000: c3b1 0a                                  ...
(注意:“0a”是来自
echo
的输出“行”末尾的换行符),但当您在MacOS扩展卷的文件名中使用它时,它会转换为分解形式U+006E U+0303(0x6ecc83):

$touchñ $ls | xxd 00000000:6ecc 830a n

在UTF-8语言环境中,这两种不同的表示形式应被视为同一个字符,但显然macOS中的
find
并不能做到这一点:

$ LC_ALL=en_US.UTF-8 find . -name '*ñ*'
$ LC_ALL=en_US.UTF-8 find . -name '*n*'
./ñ
$ LC_ALL=en_US.UTF-8 find . -name 'n?'
./ñ
在第二个和第三个命令中,
find
与“n”代码点匹配,并将组合波浪线视为其后面的一个完全独立的字符。顺便说一句,请注意,我在匹配模式周围加了引号——这很重要,因为如果没有它们,shell将在将其传递给
find
命令之前将其扩展到当前目录中的文件名列表

解决方案是什么?在模式中显式使用分解形式是一个令人讨厌的选择。您可以使用bash的
$”引用表单,允许使用
\x
指定十六进制字节:

$ find . -name $'*n\xcc\x83*'
./ñ
但事实上比这更糟糕,因为从macOS High Sierra开始,苹果使用新的苹果文件系统(APFS),它允许两种表示。由于
find
无法将它们识别为字符,因此您甚至不能使用像
-name*[ññ]*'这样的括号表达式来匹配这两个字符,您必须使用带有
-E
-regex`的扩展正则表达式,就像这样(在带有APFS的Mac上完成):

(请注意,在正则表达式中,
*
是匹配任何字符序列的方式,相当于普通“glob”通配符模式中的
*
。)


自己动手Unicode支持不是很有趣吗?

一个简单的
查找-键入f-name*ñ*
在macOS上对我有效。您正在使用什么操作系统?Mac OSX El Capitan Region设置为USA,并在~/.bash_profile export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8中导出变量尝试使用grep insteadfind-类型f|grepñ也不起作用,我想用一种简单的方法来创建西班牙语或法语的完整字母表,比如mkdir-p{a..z},但似乎我必须坚持使用mkdir-p{a..n},ñ,{o..z},谢谢你的回答。
$ touch composed-ñ decomposed-n$'\xcc\x83' unaccented-n
$ ls
composed-ñ  decomposed-ñ    unaccented-n
$ ls | xxd
00000000: 636f 6d70 6f73 6564 2dc3 b10a 6465 636f  composed-...deco
00000010: 6d70 6f73 6564 2d6e cc83 0a75 6e61 6363  mposed-n...unacc
00000020: 656e 7465 642d 6e0a                      ented-n.
$ find -E . -regex $'.*(\xc3\xb1|n\xcc\x83).*'
./composed-ñ
./decomposed-ñ