Regex gawk正则表达式没有按预期工作

Regex gawk正则表达式没有按预期工作,regex,awk,non-ascii-characters,Regex,Awk,Non Ascii Characters,我在一个awk脚本中有一个函数,它大部分是有效的,但如果通过了德语“umlaute”(äöü),它就不起作用 function sanitizeIdentifier(str){ debug( "san IN:" str) gsub(/[^_a-zA-Z0-9]/, "_", str) debug( "san OUT:" str) return str } 输出: san IN:(Vorhalt für Start/Stopp) san OUT:_Vorhalt_für_Sta

我在一个awk脚本中有一个函数,它大部分是有效的,但如果通过了德语“umlaute”(äöü),它就不起作用

function sanitizeIdentifier(str){
  debug( "san IN:" str)
  gsub(/[^_a-zA-Z0-9]/, "_", str)
  debug( "san OUT:" str)
  return str
}
输出:

san IN:(Vorhalt für Start/Stopp) 
san OUT:_Vorhalt_für_Start_Stopp__
我如何匹配umlaute或更好为什么umlaute与表达式不匹配

我的awk脚本是unicode(不带BOM的utf8),输入文件未知。 将它们转换为unicode也无济于事

只有当输入文件是unicode(这有点清楚)时,像
gsub(/ä/,“ae”,str)
这样的显式替换才有效

使用

gsub(/[^_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]/, "_", str)
替换发生的事件,但如果输入文件为Utf8,则它们将替换为两个下划线。 整个行为似乎有点奇怪


我在windows上运行GNU Awk 3.1.6(来自gnuwin32)

带有umlaut的字符超出了括号表达式中的范围,因此不匹配。字符类,如
[:alpha://code>或
[:alnum://code>应该尊重区域设置,因此我建议改为使用它们:

gsub(/[^_[:alnum:]]/, "_", str)
使用
LC_ALL=C
运行意味着使用umlaut替换字符。您可能还希望通过添加第二个替换来删除重复的

gsub(/_+/, "_", str)

@是的,我想我误解了这个问题,谢谢你指出。但这与我想要的正好相反。我想创建有效的C标识符。我确实想用下划线替换umlaute。但似乎
a-z
范围与它们匹配,以及为什么它们没有被替换。还是我误解了[:alnum:]?@vlad_tepesch我已经更新了答案。这有帮助吗?我不知道如何在windows上设置GNUutil的区域设置。[:alnum:]没有更改任何内容,现在我将在代码中保留显式字符列表-至少这会将umlaute从
echo halloä24d
直接导入
gawk“gsub…
似乎按预期工作。至少用乌姆劳特。使用德语“ß”可以得到“á”的输出。结论:仅使用完整的字符列表似乎能如预期的那样工作-带umlauts的字符听起来是什么样的,都在括号表达式的范围内。在我的系统中,字符被替换。像运行
LC_ALL=C awk…
这样的脚本会改变行为吗?在OSX上运行awk和gawk时,
u
字符也会代替我。它同时适用于
LC_ALL=C
LC_ALL=de_de
,这实际上是我所期望的,因为语言环境不应该改变像
a-z
这样的范围的含义。另一方面,当我使用
[:alpha:://code>而不是范围时,区域设置确实产生了差异,这是应该的。所有这些都说明这是一个谜。一个问题:如果您不知道输入文件的编码是什么,您是如何将它们转换为unicode的?当你说“unicode”时,你是指utf8吗?@jas unknown表示不同的输入文件之间的输入编码可能不同。我用我知道的文件测试了它。a-z范围的行为确实很奇怪。如果我将其替换为
abcdefghijklmnopqrstuvwxyz
,则字符将被替换。我正在使用windows,不知道是否有LC\U ALL等效。。。我猜那是
chcp
codepage的东西?@jas:不,
a-z
受语言环境的影响。看:是的,@cuonglm,我明白了我也看到了这里的解释:它似乎依赖于实现,因为在“C”和“POSIX”语言环境之外,范围表达式的含义是未定义的。