Все 3 из этих подходов будут работать в любой локали и будут работать для любого класса символов, просто изменяя имя класса, и будут работать для других выражений скобок или строк и т. Д.:
1) Просто ищите любойпунктируйте, но меняйте его, только если это не один из символов, которые вы не хотите менять:
$ echo 'a.b?c#d@e,f' |
awk '{
new = ""
while ( match($0,/[[:punct:]]/) ) {
chr = substr($0,RSTART,1)
new = new substr($0,1,RSTART-1) (chr ~ /[,.@]/ ? chr : "")
$0 = substr($0,RSTART+RLENGTH)
}
print new $0
}'
a.bcd@e,f
2) Сначала поверните символы, которые вы не хотите менять, в другие строки, а затем снова поверните их обратно:
$ echo 'a.b?c#d@e,f' |
awk '{
gsub(/a/,"aA"); gsub(/,/,"aB"); gsub(/\./,"aC"); gsub(/@/,"aD")
gsub(/[[:punct:]]/,"")
gsub(/aD/,"@"); gsub(/aC/,"."); gsub(/aB/,","); gsub(/aA/,"a")
print
}'
a.bcd@e,f
Изменение a
на aA
и обратно - это то, что гарантирует, что строки, которые вы создаете при преобразовании @
и т. Д., Являются строками, которые не могут существовать в других местах входных данных в то время, и поэтомупосле этого вы можете безопасно преобразовать их обратно.
3) Присвойте пунктам значение RS, затем удалите суффикс RS из символов, которые вы не хотите изменять, затем измените оставшиеся пункты с суффиксом RS:
$ echo 'a.b?c#d@e,f' |
awk '{
gsub(/[[:punct:]]/,"&"RS)
$0 = gensub("([,.@])"RS,"\\1","g")
gsub("[[:punct:]]"RS,"")
print
}'
a.bcd@e,f
Тот использует GNU awk для gensub (), а с другими awk вам понадобится match () + substr ().