首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"sed“特殊字符处理

"sed“特殊字符处理
EN

Stack Overflow用户
提问于 2014-07-22 22:33:00
回答 3查看 2.8K关注 0票数 3

我们在脚本中使用sed命令将文件内容替换为变量中的值

例如..

代码语言:javascript
复制
export value="dba01upc\Fusion_test"
sed -i "s%{"sara_ftp_username"}%$value%g" /home_ldap/user1/placeholder/Sara.xml

sed命令将忽略诸如'\‘之类的特殊字符,并替换为不带'\’的字符串"dba01upcFusion_test“。如果我像export value='dba01upc\Fusion_test‘(使用'\’括在‘’中)进行导出,则该命令有效。但不幸的是,我们的客户想要导出带有单/双引号的原始文本dba01upc\Fusion_test,并且他不想在文本中添加任何额外的字符。有没有人可以告诉我怎么让sed来放置带有特殊字符的文本..

更换前: Sara.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<ser:service-account >
<ser:description/>
<ser:static-account>
<con:username>{sara_ftp_username}</con:username>
</ser:static-account>
</ser:service-account>

更换后: Sara.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<ser:service-account>
<ser:description/>
<ser:static-account>
<con:username>dba01upcFusion_test</con:username>
</ser:static-account>
</ser:service-account>

提前感谢

EN

回答 3

Stack Overflow用户

发布于 2014-07-23 05:52:55

使用sed不能很好地解决这个问题。只需使用awk即可:

代码语言:javascript
复制
awk -v old="string1" -v new="string2" '
idx = index($0,old) {
    $0 = substr($0,1,idx-1) new substr($0,idx+length(old))
}
1' file

啊,@mklement0有一个很好的观点--为了防止转义被解释,你需要传入arg列表中的值和文件名,然后从文件名中赋值,而不是用-v赋值给变量(参见我很久以前在http://cfajohnson.com/shell/cus-faq-2.html#Q24上为comp.unix.shell常见问题解答写的摘要,但显然忘记了!)。

以下代码将在每行找到的每个搜索字符串上进行所需的替换(a\ta -> e\tf):

代码语言:javascript
复制
$ cat tst.awk
BEGIN {
    old=ARGV[1]; delete ARGV[1]
    new=ARGV[2]; delete ARGV[2]
    lgthOld = length(old)
}
{
    head = ""; tail = $0
    while ( idx = index(tail,old) ) {
        head = head substr(tail,1,idx-1) new
        tail = substr(tail,idx+lgthOld)
    }
    print head tail
}

$ cat file
a\ta    a       a       a\ta

$ awk -f tst.awk 'a\ta' 'e\tf' file
e\tf    a       a       e\tf

file中的空格是制表符。如果您愿意,您可以将ARGV3向下移动并调整ARGC,但在大多数情况下这并不是必需的。

票数 3
EN

Stack Overflow用户

发布于 2014-07-23 23:13:33

利用后见之明更新,以呈现options

  • Update 2:如果您打算使用,请参阅--有点麻烦,但现在健壮且通用-- solution below.
  • If您需要一个能够正确处理任意搜索和替换字符串(但不能合并单词边界断言等正则表达式功能)的健壮、自包含的solution。参阅Ed Morton's answer.
  • If如果您想要一个Python纯bash 解决方案,并且您的输入文件很小并且保留多个尾随换行符并不重要,请参阅您想要一个Python完整的第三方模板解决方案<代码>E242,例如,考虑j2cliJinja2的模板-如果您有Python和pip,使用sudo pip install j2cli安装。

简单示例(请注意,由于替换字符串是通过文件提供的,因此这可能不适用于敏感数据;请注意双花括号({{...}})):

dba01upc\Fusion_test =‘dba01upc\Fusion_test’echo "sara_ftp_username=$value“>data.env echo >data.env >tmpl.xml j2 tmpl.xml data.env # -> Dba01upc

如果您使用sed**,,则需要仔细转义搜索和替换字符串**,因为:

  • 正如Ed Morton在其他地方的评论中指出的那样,sed不支持使用文字字符串作为替换字符串-它总是解释替换字符串中的特殊字符/序列。必须以不会将其字符误认为特殊正则表达式字符的方式对搜索字符串文字进行转义。

下面使用两个通用助手函数来执行此转义(引用),这两个函数应用了"Is it possible to escape regex characters reliably with sed?"中介绍的技术

代码语言:javascript
复制
#!/usr/bin/env bash

# SYNOPSIS
#   quoteRe <text>
# DESCRIPTION
#   Quotes (escapes) the specified literal text for use in a regular expression,
#   whether basic or extended - should work with all common flavors.
quoteRe() { sed -e 's/[^^]/[&]/g; s/\^/\\^/g; $!a\'$'\n''\\n' <<<"$1" | tr -d '\n'; }

# '

# SYNOPSIS
#  quoteSubst <text>
# DESCRIPTION
#  Quotes (escapes) the specified literal string for safe use as the substitution string (the 'new' in `s/old/new/`).
quoteSubst() {
  IFS= read -d '' -r < <(sed -e ':a' -e '$!{N;ba' -e '}' -e 's/[&/\]/\\&/g; s/\n/\\&/g' <<<"$1")
  printf %s "${REPLY%$'\n'}"    
}

# The search string.
search='{sara_ftp_username}'

# The replacement string; a demo value with characters that need escaping.
value='&\1%"'\'';<>/|dba01upc\Fusion_test'

# Use the appropriately escaped versions of both strings.
sed "s/$(quoteRe "$search")/$(quoteSubst "$value")/g" <<<'<el>{sara_ftp_username}</el>'

# -> <el>&\1%"';<>/|dba01upc\Fusion_test</el>

  • quoteRe()quoteSubst() 都能正确处理多行字符串。但是,
    • 注意到,由于sed在缺省情况下一次只读取一行,因此只有在显式读取once.

中的多行(或所有行)的sed命令中,才能将quoteRe()与多行字符串一起使用

与命令替换(**$(...)**),一起使用时,

  • quoteRe()始终是安全的,因为它始终返回单行字符串(输入中的换行符编码为'\n').
  • By $(...),,如果使用quoteSubst()时字符串的末尾换行符为,则不能使用换行符因为后者将删除最后一个尾随的换行符,从而破坏编码(因为quoteSubst() \-escapes实际换行符,所以返回的字符串将以悬空的\结尾)。因此,对于带有尾随换行符的command.

字符串,请先使用IFS= read -d '' -r escapedValue < <(quoteSubst "$value")将转义值读取到一个单独的变量中,然后在

  • command.

中使用该变量

票数 3
EN

Stack Overflow用户

发布于 2014-07-24 01:59:45

这可以通过单独使用bash内建来完成--没有sed、没有awk等等。

代码语言:javascript
复制
orig='{sara_ftp_username}'               # put the original value into a variable
new='dba01upc\Fusion_test'               # ...no need to 'export'!

contents=$(<Sara.xml)                    # read the file's content into
new_contents=${contents//"$orig"/$new}   # use parameter expansion to replace
printf '%s' "$new_contents" >Sara.xml    # write new content to disk

有关使用参数扩展进行字符串替换的信息,请参阅the relevant part of BashFAQ #100

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24890230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档