linux 值sed命令

转自:


http://www.cnblogs.com/dong008259/archive/2011/12/07/2279897.html

sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作,下面先了解一下sed的用法
sed命令行格式为:
         sed [-nefri] ‘command’ 输入文本        

常用选项:
        
-n∶使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到萤幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
        -e∶直接在指令列模式上进行 sed 的动作编辑;
        -f∶直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作;
        -r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
        -i∶直接修改读取的档案内容,而不是由萤幕输出。
       

常用命令:
        a   ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
        c   ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
        d   ∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
         i   ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
         p  ∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~
         s  ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

举例:(假设我们有一文件名为ab)
     删除某行
     [root@localhost ruby] # sed '1d' ab              #删除第一行 
     [root@localhost ruby] # sed '$d' ab              #删除最后一行
     [root@localhost ruby] # sed '1,2d' ab           #删除第一行到第二行
     [root@localhost ruby] # sed '2,$d' ab           #删除第二行到最后一行

  显示某行
.    [root@localhost ruby] # sed -n '1p' ab           #显示第一行 
     [root@localhost ruby] # sed -n '$p' ab           #显示最后一行
     [root@localhost ruby] # sed -n '1,2p' ab        #显示第一行到第二行
     [root@localhost ruby] # sed -n '2,$p' ab        #显示第二行到最后一行

  使用模式进行查询
     [root@localhost ruby] # sed -n '/ruby/p' ab    #查询包括关键字ruby所在所有行
     [root@localhost ruby] # sed -n '/\$/p' ab        #查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含义

  增加一行或多行字符串
     [root@localhost ruby]# cat ab
     Hello!
     ruby is me,welcome to my blog.
     end
     [root@localhost ruby] # sed '1a drink tea' ab  #第一行后增加字符串"drink tea"
     Hello!
     drink tea
     ruby is me,welcome to my blog. 
     end
     [root@localhost ruby] # sed '1,3a drink tea' ab #第一行到第三行后增加字符串"drink tea"
     Hello!
     drink tea
     ruby is me,welcome to my blog.
     drink tea
     end
     drink tea
     [root@localhost ruby] # sed '1a drink tea\nor coffee' ab   #第一行后增加多行,使用换行符\n
     Hello!
     drink tea
     or coffee
     ruby is me,welcome to my blog.
     end

  代替一行或多行
     [root@localhost ruby] # sed '1c Hi' ab                #第一行代替为Hi
     Hi
     ruby is me,welcome to my blog.
     end
     [root@localhost ruby] # sed '1,2c Hi' ab             #第一行到第二行代替为Hi
     Hi
     end

  替换一行中的某部分
  格式:sed 's/要替换的字符串/新的字符串/g'   (要替换的字符串可以用正则表达式)
     [root@localhost ruby] # sed -n '/ruby/p' ab | sed 's/ruby/bird/g'    #替换ruby为bird
   [root@localhost ruby] # sed -n '/ruby/p' ab | sed 's/ruby//g'        #删除ruby

     插入
     [root@localhost ruby] # sed -i '$a bye' ab         #在文件ab中最后一行直接输入"bye"
     [root@localhost ruby]# cat ab
     Hello!
     ruby is me,welcome to my blog.
     end
     bye


<think>我们正在处理用户的问题:在Linux shell脚本中使用sed命令时如何引用变量的。 用户希望知道如何在sed命令中正确地使用shell变量。 根据之前的知识,我们知道sed命令通常使用单引号来避免shell对特殊字符的扩展。但是,如果需要在sed命令中使用变量,就需要打破单引号的限制,因为单引号内不会解析变量。 常见的解决方法有: 1. 使用双引号:将整个sed命令用双引号括起来,这样变量就会被shell扩展。但是需要注意,双引号内会对特殊字符(如`$`、`\`、`!`等)进行解释,所以如果替换字符串中包含这些字符,需要小心转义。 2. 使用单引号拼接变量:将变量部分用单引号分隔开,然后与单引号字符串拼接。 3. 使用sed的另一种分隔符:如果变量中包含斜杠(/),为了避免与sed的分隔符冲突,可以使用其他字符作为分隔符,如#、|等。 另外,需要注意,如果变量中包含特殊字符(如斜杠、反斜杠、&等),在sed中可能会被解释为命令的一部分,因此需要对变量进行转义。但是,转义变量可能会很复杂,因为不同的sed版本(如GNU sed和BSD sed)对转义的处理可能不同。 我们来看几个例子: 例1:使用双引号,并转义特殊字符(比如斜杠) 假设我们有一个变量var="hello/world",我们想用sed替换一个模式为这个变量命令可能如下: sed "s/pattern/$(echo $var | sed 's/\//\\\//g')/g" file 这里我们使用了子shell来对变量中的斜杠进行转义,将其替换为\/,这样在sed中就不会被当作分隔符了。但是这种方法比较繁琐。 例2:使用不同的分隔符(比如使用#): sed "s#pattern#$var#g" file 这样,即使$var中包含斜杠,也不会影响,因为sed使用#作为分隔符。 例3:使用单引号拼接: sed 's/pattern/'"$var"'/g' file 注意:这里整个sed命令由三部分组成:'s/pattern/'、双引号引用的变量$var、以及'/g'。这样变量会被扩展,而其他部分在单引号内不会被扩展。 但是,如果变量中包含特殊字符(如&、\等),在替换字符串中,&表示整个匹配的内容,所以如果变量中包含&,会导致非预期的结果。因此,我们需要在变量中将对sed有特殊意义的字符进行转义。例如,将&替换为\&。 因此,更健壮的方法是在变量使用前进行转义: var_escaped=$(sed 's/[&/\]/\\&/g' <<< "$var") sed 's/pattern/'"$var_escaped"'/g' file 但是,这种方法需要两次调用sed,效率较低。 考虑到用户可能使用的是GNU sed,我们可以使用更简单的双引号方式,并配合使用不同的分隔符来避免斜杠问题,同时使用变量转义函数来处理其他特殊字符。 然而,根据引用[5]中提到的sed命令,我们注意到sed命令中可以使用y命令进行字符替换,但这里我们主要讨论的是s命令(替换)。 因此,我们给出以下建议: 1. 如果变量中不包含斜杠(/)和特殊字符(如&),可以直接使用双引号: sed "s/pattern/$var/g" file 2. 如果变量中包含斜杠,但其他特殊字符不多,可以改变分隔符: sed "s|pattern|$var|g" file 3. 如果变量中包含特殊字符(如&、\、/等),需要先对变量进行转义,然后使用: # 转义函数(针对sed的替换字符串中的特殊字符) escape_var() { sed 's/[&/\]/\\&/g' <<< "$1" } escaped_var=$(escape_var "$var") sed "s/pattern/$escaped_var/g" file 注意:上面的转义函数只转义了&、/和\,但sed的替换字符串中还有其他特殊字符,比如`\n`(代表换行)和`\1`(后向引用)等,如果变量中包含反斜杠,那么它可能会影响这些转义序列。因此,如果变量中包含反斜杠,并且希望它作为字面反斜杠,那么就需要转义。但是,如果变量中本来就包含转义序列(比如\n代表换行),那么转义后(变成\\n)就会变成字面的\n,而不是换行。所以,转义必须根据需求来定。 通常,我们只是希望将变量原封不动地替换进去,所以需要将变量中所有对sed有特殊意义的字符都转义。这些字符包括:&、\、/(如果使用/作为分隔符)、以及替换字符串中的`\`后跟数字(后向引用)等。但后向引用我们通常不希望被解释,所以应该转义反斜杠。 因此,更全面的转义函数可以是: escape_var() { # 转义&、\、/(即使我们可能使用其他分隔符,但为了通用,转义/) # 同时,为了处理换行,我们可以使用:将换行符替换为\n(转义后的换行),但这里我们假设变量是单行 # 如果变量是多行,那么sed的替换部分通常不能包含换行(除非使用特殊方式),所以一般我们处理单行变量。 sed -e 's/[&/\]/\\&/g' <<< "$1" } 但是,如果变量包含多行,那么上面的转义函数会处理每一行,但整个替换字符串中插入换行会导致sed命令出错(因为s命令的替换字符串中不能包含换行符,除非使用特殊版本或选项)。所以,通常我们要求变量是单行。 综上所述,在shell脚本中使用sed命令引用变量时,需要根据变量的内容选择合适的方法。 下面我们给出一个完整的示例: 示例:将文件中的“oldtext”替换为变量$new_text的内容,变量内容可能包含特殊字符。 步骤: 1. 对变量进行转义(处理特殊字符) 2. 使用sed命令进行替换,为了避免斜杠问题,我们可以使用不同的分隔符,比如|。 脚本: ```bash #!/bin/bash # 定义要替换的新文本 new_text="This & that / something \\ else" # 转义函数 escape_var() { # 转义&、\、/(这里我们使用|作为分隔符,所以/不需要转义,但为了通用,我们还是转义,因为转义后也没问题) # 注意:这里我们转义了&、\、/,并且我们使用|作为分隔符,所以/不会被误解。 # 但是,如果变量中包含|,那么我们需要选择另一个分隔符,或者对|也进行转义?实际上,在分隔符是|的情况下,替换字符串中的|不需要转义。 # 所以,我们只转义&和反斜杠,以及换行符(这里假设是单行,所以不考虑换行) # 我们只转义&和反斜杠,因为斜杠(/)在替换字符串中不是特殊字符(除非使用/作为分隔符),但为了通用,我们转义&和反斜杠。 # 注意:在替换字符串中,反斜杠用于转义,所以我们需要将字面的反斜杠写成\\,因此变量中的每个反斜杠都需要转义成两个反斜杠。 # 同时,&在替换字符串中代表整个匹配,所以必须转义成\&。 # 所以,我们进行两次替换:先将反斜杠转义成两个反斜杠,然后将&转义成\&。 # 注意顺序:先转义反斜杠,再转义&,否则转义&时引入的反斜杠又会被转义。 sed -e 's/\\/\\\\/g' -e 's/&/\\&/g' <<< "$1" } escaped_text=$(escape_var "$new_text") # 使用|作为分隔符,避免变量中的斜杠影响 sed -i "s|oldtext|$escaped_text|g" file.txt ``` 注意:上面的转义函数只处理了反斜杠和&,因为我们使用了|作为分隔符,所以斜杠(/)不需要转义。如果变量中包含|,那么我们可以选择另一个在变量中不存在的字符作为分隔符,或者对|进行转义(但替换字符串中的分隔符不需要转义,除非在模式部分)。所以,选择不包含在变量中的分隔符是最简单的。 如果变量中同时包含|和/,那么我们可以选择其他字符,比如@、#、!等。 另外,上面的脚本中使用了-i选项,这是GNU sed的选项,用于直接修改文件。如果是在BSD sed(如macOS)中,需要写成-i ''。 总结:在shell脚本中使用sed命令引用变量时,关键点在于: - 选择合适的引号(双引号)以允许变量扩展 - 处理变量中的特殊字符,特别是当这些字符在sed的替换字符串中有特殊含义时 - 考虑使用不同的分隔符以避免斜杠问题 - 对变量进行转义 根据引用[4]中提到的,Shell脚本用于自动化任务,因此正确使用sed命令并处理变量是非常重要的。 现在,我们根据用户的问题,给出一个直接的回答。 回答: 在Linux shell脚本中,在sed命令中使用变量时,由于sed命令通常使用单引号来避免shell扩展,但这样就不能使用变量。因此,我们需要使用双引号来包裹sed命令,以便变量被扩展。但是,双引号内变量中的特殊字符可能会干扰sed命令的执行。以下是几种处理方法: 1. 使用双引号包裹整个sed命令,并确保变量中不包含特殊字符(如/、&等): sed "s/pattern/$var/g" file 2. 如果变量中包含斜杠(/),可以使用其他分隔符(如#、|等): sed "s|pattern|$var|g" file 3. 如果变量中包含特殊字符(如&、\等),需要先对变量进行转义,再使用: # 转义函数示例(转义&和反斜杠) escape_var() { local escaped_value escaped_value=$(printf '%s\n' "$1" | sed -e 's/[&]/\\&/g' -e 's/[\]]/\\&/g') # 注意:这里我们只转义了&和[,但实际上,根据情况可能需要转义更多字符。 # 另一种更通用的方法:转义所有在替换字符串中有特殊意义的字符:&、\、分隔符(如果我们使用/,则转义/)等。 # 但更简单的方式是使用不同的分隔符并转义&和反斜杠。 echo "$escaped_value" } escaped_var=$(escape_var "$var") sed "s|pattern|$escaped_var|g" file 注意:如果变量中包含换行符,那么上述方法可能不适用,因为sed的s命令的替换字符串中不能包含换行符。在这种情况下,可能需要考虑其他工具,如awk。 另外,如果使用较新版本的GNU sed(4.4以上),可以使用`sed -e "s/pattern/${var//\//\\\/}/g"`,但这样只能转义斜杠,不能处理&等。 因此,推荐使用分隔符和转义函数的方法。 最后,我们提供一个更健壮的转义函数,用于转义替换字符串中的特殊字符(针对使用/作为分隔符的情况,但也可以用于其他分隔符,只要在转义时也转义分隔符): escape_sed_replacement() { # 转义替换字符串中的:&、\、/(分隔符)和换行符(转换为\n) # 注意:换行符需要特殊处理,因为替换字符串中不能有换行符,但我们可以将其转换为\n(转义序列) # 这里我们只处理单行变量,所以不处理换行符,假设变量是单行。 local str="$1" # 先转义反斜杠 str="${str//\\/\\\\}" # 再转义& str="${str//&/\\&}" # 如果使用/作为分隔符,则转义/ str="${str////\\/}" # 注意:如果是其他分隔符,则不需要转义斜杠,但转义了也没关系(会变成\/,在替换字符串中就是字面的\/) echo "$str" } 然后这样使用: escaped_var=$(escape_sed_replacement "$var") sed "s/pattern/$escaped_var/g" file 但是,如果使用其他分隔符,比如|,那么就不需要转义斜杠,所以可以修改函数,使其可以接受一个分隔符参数,但这样会复杂。因此,通常我们选择在函数中只转义&和反斜杠,然后使用不同的分隔符(如|)来避免转义斜杠。 因此,一个更简单且通用的转义函数(只转义&和反斜杠)是: escape_sed_replacement() { printf '%s\n' "$1" | sed -e 's/[&]/\\&/g' -e 's/[\\]/\\\\/g' } 然后在使用时,选择一个在变量中不会出现的字符作为分隔符,比如|、#、@等。 示例脚本: ```bash #!/bin/bash # 要替换的文本 new_text="This & that / something \\ else | and more" # 转义函数:转义&和反斜杠 escape_sed_replacement() { printf '%s' "$1" | sed -e 's/[&]/\\&/g' -e 's/[\\]/\\\\/g' } escaped_text=$(escape_sed_replacement "$new_text") # 使用#作为分隔符,因为变量中可能包含|和/ sed -i "s#oldtext#$escaped_text#g" file.txt ``` 这样,即使变量中包含&、\、/、|等字符,也能正确替换。 注意:上面的转义函数中,我们使用printf '%s'来避免在最后添加换行符(如果变量本身没有换行)。但是,如果变量本身包含换行符,那么仍然会出错。因此,如果变量可能包含换行符,我们需要在转义函数中处理换行符,将其替换为\n(转义序列)。但是,在替换字符串中,sed支持用\n表示换行,所以我们可以将变量中的换行符替换为\n(注意:在替换字符串中,\n表示换行)。但是,在转义函数中,我们需要先将换行符替换为\n字符串,同时还要转义反斜杠和&。 处理换行符的转义函数: escape_sed_replacement() { # 将换行符替换为\n,同时转义反斜杠和& # 注意:由于sed处理多行,我们需要使用特殊技巧 # 使用awk可能更简单,但我们这里用sed,需要小心 # 首先,将每个反斜杠替换为两个反斜杠(这样后面替换换行时不会影响) # 然后,将&替换为\& # 最后,将换行符替换为\n(注意:在替换字符串中,我们需要写\\n,因为要输出\n,所以需要两个反斜杠?) # 实际上,在替换字符串中,要表示一个换行符,我们需要写\n,但是因为我们在用sed生成一个字符串,这个字符串中的\n会被sed解释为换行,但我们不希望这样,我们希望生成一个字符串,其中包含字面的\和n。 # 所以,我们需要将换行符替换为两个字符:反斜杠和n。 # 但是,在替换操作中,我们需要先转义反斜杠,这样在替换换行时,不会影响。 # 步骤: # 1. 转义反斜杠:s/\\/\\\\/g # 2. 转义&:s/&/\\&/g # 3. 替换换行:s/\n/\\n/g (注意:这里\n代表换行符) # 但是,在sed中处理换行符比较麻烦,因为模式空间通常不包含换行符(除非使用-z选项,但这样会把整个文件作为一行,以空字符分隔,但这里变量是字符串,可能包含换行)。 # 因此,我们使用tr将换行符替换为一个特殊字符,然后再用sed处理,最后再替换回来?但这样复杂。 # 另一种方法:使用awk # 这里我们使用sed并假设输入是单行,所以不处理多行。如果有多行,则使用以下方法: # 使用sed的循环,但比较复杂。 # 因此,我们建议:如果变量包含多行,那么最好重新考虑,因为sed的s命令替换部分通常不支持多行(除非使用高级技巧)。在大多数情况下,变量是单行的。 # 所以,我们只处理单行变量(即不包含换行符)。如果变量包含换行,则报错或使用其他方法。 if [[ "$1" = *$'\n'* ]]; then echo "Error: Variable contains newline, which is not supported." >&2 exit 1 fi printf '%s' "$1" | sed -e 's/[\]/\\\\/g' -e 's/[&]/\\&/g' } 因此,在实际使用中,确保变量是单行字符串。 如果确实需要处理多行变量,那么可以使用sed的z选项(GNU sed)将整个输入视为一行(以空字符分隔),然后进行替换,但这样会改变文件中的空字符,所以不常用。或者使用其他工具如awk。 综上所述,在shell脚本中使用sed命令引用变量时,推荐使用分隔符和转义函数(转义&和反斜杠)的方法,并确保变量是单行。 最后,我们生成相关问题。</think>在 Linux shell 脚本中使用 `sed` 命令引用变量时,需要特别注意单引号、双引号和转义字符的处理。以下是几种常用方法及示例: --- ### 方法 1:双引号包裹整个 sed 命令(推荐) **原理**:双引号允许解析变量,但需转义 `$`、`"`、`\` 等特殊字符。 ```bash #!/bin/bash old_str="hello" new_str="world" sed -i "s/${old_str}/${new_str}/g" file.txt # 替换文件中的 hello 为 world ``` --- ### 方法 2:拼接单引号与双引号 **原理**:将变量放在双引号中,其他部分用单引号包裹。 ```bash #!/bin/bash pattern="error" replacement="success" sed 's/'"$pattern"'/'"$replacement"'/g' file.txt ``` --- ### 方法 3:使用其他分隔符(避免路径冲突) 当变量包含 `/` 时(如路径),改用 `#`、`|` 等作为分隔符: ```bash #!/bin/bash dir="/home/user/docs" sed "s#/old/path#$dir#g" config.conf # 替换路径 ``` --- ### 方法 4:转义特殊字符 若变量包含正则元字符(如 `.`、`*`),需先转义: ```bash #!/bin/bash input="file.name" escaped_input=$(sed 's/[.*]/\\&/g' <<< "$input") # 转义 . 和 * sed "s/$escaped_input/replaced/g" data.txt ``` --- ### 关键注意事项 1. **引号规则**: - 单引号 `' '`:内部内容原样输出,**不解析变量**。 - 双引号 `" "`:**解析变量和命令**,但需转义特殊字符。 - 反引号或 `$()`:执行命令并替换结果。 2. **特殊字符处理**: - 若变量含 `&`(表示匹配项),需转义为 `\&`。 - 若变量含换行符,需用 `tr` 或 `awk` 预处理。 3. **效率问题**: - 多次调用 `sed` 转义变量可能降低性能,建议优先使用分隔符替换法。 --- ### 完整示例脚本 ```bash #!/bin/bash # 定义变量 original="Hello, [2023]" replacement="Goodbye, 2024" # 转义正则特殊字符(如 [ ]) escaped_original=$(sed 's/[][.*^$]/\\&/g' <<< "$original") # 执行替换 sed -i "s/$escaped_original/$replacement/g" target_file.txt ``` > **执行结果**:将 `target_file.txt` 中所有 `Hello, [2023]` 替换为 `Goodbye, 2024`。 通过以上方法,可安全地在 `sed` 命令中引用变量,适用于配置文件修改、日志处理等自动化任务[^4]。 --- ### 相关问题 1. 如何在 `awk` 命令中使用 shell 变量? 2. `sed` 和 `awk` 在处理变量时有何主要区别? 3. 如何避免 shell 脚本中变量替换的安全风险(如命令注入)? 4. 在 `sed` 命令中如何正确处理包含空格的变量? [^1]: Shell 是用户和 Unix/Linux 内核沟通的桥梁,用户的大部分工作都是通过 Shell 完成的。 [^4]: Shell 脚本通常用于系统管理任务,如文件处理、程序调度、系统配置等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值