替换子字符串中的非字母数字字符
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 对逐行读取到 key
和 value
变量中。
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:]]/,"_")}'
我正在尝试用 _
:[=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 对逐行读取到 key
和 value
变量中。
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 thesub
function, exceptgsub
replaces all of the longest, leftmost, nonoverlapping matching substrings it can find. Theg
ingsub
stands for global, which means replace everywhere,Thegsub
function returns the number of substitutions made
+1
每当 gsub returns 0
{print [=25=]}
以为我会在 ruby 中投入一点:
ruby -pe '$_.sub!(/[^=]+/){|m| m.gsub(/[^[:alnum:]]/,"_")}'