替换子字符串中的非字母数字字符

Replace non-alphanumeric characters in substring

我正在尝试用 _:[=15= 替换一堆键值对的第一部分(= 符号之前)中出现的任何非字母数字字符]

输入

aa:cc:dd=foo-bar|17657V70YPQOV
ee-ff/gg=barFOO

期望输出

aa_cc_dd=foo-bar|17657V70YPQOV
ee_ff_gg=barFOO

我尝试过以下模式:s/\([^a-zA-Z]*\)=\(.*\)/=/g 但没有成功。任何基本的 GNU/Linux 工具都可以使用。

假设您的输入在一个名为 infile 的文件中,您可以这样做:

while IFS== read key value; do
    printf '%s=%s\n' "${key//[![:alnum:]]/_}" "${value}"
done < infile

与输出

aa_cc_dd=foo-bar|17657V70YPQOV
ee_ff_gg=barFOO

这会将 IFS 变量设置为 = 并将您的 key/value 对逐行读取到 keyvalue 变量中。

printf 命令打印它们并将 = 添加回去; "${key//[![:alnum:]]/_}"key 中的所有 non-alphanumeric 个字符替换为下划线。

awk

$ awk -F= -v OFS='=' '{gsub("[^a-zA-Z]", "_", )} 1' ip.txt 
aa_cc_dd=foo-bar|17657V70YPQOV
ee_ff_gg=barFOO

输入和输出字段分隔符设置为 =,然后 gsub("[^a-zA-Z]", "_", ) 将仅在第一个字段

中用 _ 替换所有 non-alphabet 个字符


随着 perl

$ perl -pe 's/^[^=]+/$&=~s|[^a-z]|_|gir/e' ip.txt 
aa_cc_dd=foo-bar|17657V70YPQOV
ee_ff_gg=barFOO
  • ^[^=]+= 行开头的字符
  • $&=~s|[^a-z]|_|gir 仅将匹配部分 non-alphabet 字符替换为 _
  • 使用 perl -i -pe 进行就地编辑

任何 Posix 合规 awk

$ cat f
aa:cc:dd=foo-bar|17657V70YPQOV
ee-ff/gg=barFOO

$ awk 'BEGIN{FS=OFS="="}gsub(/[^[:alnum:]]/,"_",)+1' f
aa_cc_dd=foo-bar|17657V70YPQOV
ee_ff_gg=barFOO

说明

BEGIN{FS=OFS="="} 设置输入和输出字段分隔符=

/[^[:alnum:]]/ 匹配列表中不存在的字符, [:alnum:] 匹配字母数字字符 [a-zA-Z0-9]

gsub(REGEXP, REPLACEMENT, TARGET) This is similar to the sub function, except gsub replaces all of the longest, leftmost, nonoverlapping matching substrings it can find. The g in gsub stands for global, which means replace everywhere,The gsub function returns the number of substitutions made

+1 每当 gsub returns 0

时,它都会处理默认操作 {print [=25=]}

以为我会在 ruby 中投入一点:

ruby -pe '$_.sub!(/[^=]+/){|m| m.gsub(/[^[:alnum:]]/,"_")}'