Chinaunix

标题: sed如何替换特殊字符:单引号、大于号、等号? [打印本页]

作者: lzfzl    时间: 2007-12-13 14:30
标题: sed如何替换特殊字符:单引号、大于号、等号?
想用sed s命令替换包含单引号、大于号、等号的大型文本
='换成=\'
'>换成\'>
\n换成\\n
\r换成\\r
使用过程中发现\为转义字符
sed -i.bak 's/\\n/\\\\n/g' bigtext.txt
sed -i 's/\\r/\\\\r/g' bigtext.txt
sed -i 's/=''/=\\''/g' bigtext.txt
都能正确替换
'>不知道如何替换成\'>
作者: ailms    时间: 2007-12-13 14:51

  1. [root@mail ~]# cat a
  2. ='
  3. '>
  4. \n
  5. \r
  6. [root@mail ~]# sed "s/'>/\\\'>/" a
  7. ='
  8. \'>
  9. \n
  10. \r
  11. [root@mail ~]#
复制代码

作者: lzfzl    时间: 2007-12-13 16:09
多谢精灵使!

作者: MYSQLER    时间: 2007-12-13 16:58
原帖由 ailms 于 2007-12-13 14:51 发表

[root@mail ~]# cat a
='
'>
\n
\r
[root@mail ~]# sed "s/'>/\\\'>/" a
='
\'>
\n
\r
[root@mail ~]#



我试了下这个sed "s/'>/\\'>/" a结果不正确..请问这句中\\'>和\\\'>的区别
作者: ailms    时间: 2007-12-13 20:51
你用 echo 输出就知道了


  1. echo \\
复制代码


  1. echo \\\
复制代码

作者: MYSQLER    时间: 2007-12-14 11:04
请看:

  1. [root@mail /]# echo \\v
  2. \v
  3. [root@mail /]# echo \\\v
  4. \v
复制代码

作者: MYSQLER    时间: 2007-12-14 12:57
再请看:
  1. [root@mail test]# echo \\\\v
  2. \\v
  3. [root@mail test]# echo \\\\\v
  4. \\v
  5. [root@mail test]# echo \\\\\\v
  6. \\\v
  7. [root@mail test]#
复制代码


显示出来的\是不是可以看做这个

就是说输入的总是除以2得到的余数..但是发现

echo \\v 不是这样的..其它的好像都是
作者: ailms    时间: 2007-12-14 13:38
上面给你的例子你执行就知道了,^_^
作者: MYSQLER    时间: 2007-12-14 13:40
  1. [root@linuxbash ~]# echo \\
  2. \
  3. [root@linuxbash ~]# echo \\\
  4. >
复制代码


不解..

还有7楼我写的正确否?
作者: ailms    时间: 2007-12-14 14:02
再举一个例子


  1. Script started on Fri 14 Dec 2007 01:57:04 PM CST
  2. [root@home1 ~]# echo \
  3. > 2
  4. 2
  5. [root@home1 ~]# echo ok\
  6. > 2
  7. ok2
  8. [root@home1 ~]# echo ok\\
  9. ok\
  10. [root@home1 ~]# echo ok\\\
  11. > 2
  12. ok\2
  13. [root@home1 ~]# exit
  14. exit

  15. Script done on Fri 14 Dec 2007 01:57:50 PM CST
复制代码

作者: MYSQLER    时间: 2007-12-14 14:13
还是不解..郁闷..能不能说清楚点啊..非常感谢ailms的热情帮助..
作者: MYSQLER    时间: 2007-12-14 15:26
原帖由 ailms 于 2007-12-14 14:57 发表
单纯 \\'>和\\\'> 并没有区别,但你要放到整个 sed 的表达式,和前面的 " ' " 一起看啊,

加个 \ 就是为了去掉 ' 字符的 quoting 含义,变成一个普通字符




你指的和前面的"'"一起看?
[root@mail ~]# cat a
='
'>
\n
\r
[root@mail ~]# sed "s/'>/\\\'>/" a
='
\'>
\n
\r
[root@mail ~]#


红色的那个?还是后面那个?
作者: MYSQLER    时间: 2007-12-14 15:38
这我就有疑问了..后面的'> 前要加\前边的那个'>为什么不需要加\
作者: ailms    时间: 2007-12-14 15:47
to  MYSQLER ,前面的解释有点问题,现在重新解释一下

sed "s/'>/\\'>/" 中,由于 \ 在 “ ”中保留其 escape 的作用,所以 "\\'>" 会被解释为 "\'>" ,

而送给 sed 后,应该是再一次转义为 "'>" 。

而 在 sed "s/'>/\\\'>/" 中,"\\\'>" 会被扩展为 "\\'>" ,送给 sed 就再转义就成为 "\'>" ,而现在的这个 \

不再具备 escape 的含义了,变成一个普通字符被输出

这就是我的理解 ^_^
作者: MYSQLER    时间: 2007-12-14 15:58
感谢ailms兄不耐其烦的指教

而送给 sed 后,应该是再一次转义为 "'>"

现在想知道的是sed本身为什么还要再转义一次?
作者: ailms    时间: 2007-12-14 16:02
你可以看下面的例子


  1. Script started on Fri 14 Dec 2007 03:57:18 PM CST
  2. [root@home1 temp]# echo "\\\\"
  3. \\
  4. [root@home1 temp]# echo -e "\\\\"
  5. \
  6. [root@home1 temp]# echo "\\\\"|sed "s/.*/\\\\/"
  7. \
  8. [root@home1 temp]# exit
  9. exit

  10. Script done on Fri 14 Dec 2007 03:57:41 PM CST
复制代码


因为 "\\\\" 会别 shell 扩展为 "\\" ,现在的这两个 \\ 都没有了 escape 的功能,所以第一个 echo 输出的是两个 \

在第2个例子中,由于加了 -e ,会导致 echo 在 shell 扩展为 "\\" 再重新扫描一次,这样第1个 \ 就把第2个 \ 给 escape  了,所以就只输出1个 \ 而已

第3个例子就是为了证明上面我说的 sed 会把 "\'>" 再次扩展为 "'>" 的观点

不知道明白了吗?
作者: ailms    时间: 2007-12-14 16:03
原帖由 MYSQLER 于 2007-12-14 15:58 发表
感谢ailms兄不耐其烦的指教

而送给 sed 后,应该是再一次转义为 "'>"

现在想知道的是sed本身为什么还要再转义一次?


没什么,温故而知新,我也加深了一些认识
作者: ailms    时间: 2007-12-14 16:04
有问题今晚再说了,我今天的本本都重启 N 遍了
作者: MYSQLER    时间: 2007-12-14 16:07
顺便问一下

  1. [root@shell]# echo "\\\v"
  2. \\v
  3. [root@shell]# echo \\\v
  4. \v
复制代码


这两个的区别在哪.我也看过shell的13问关于这部分的..无奈水平有限
作者: MYSQLER    时间: 2007-12-14 16:08
原帖由 ailms 于 2007-12-14 16:04 发表
有问题今晚再说了,我今天的本本都重启 N 遍了




实在是不好意思啊..哪天我发了..给你运一火车本本..
作者: ailms    时间: 2007-12-14 16:28
下面是 bash man 中关于 Quoting 一节,

可以解释上面的问题

QUOTING
       Quoting is used to remove the special meaning of certain characters or
       words  to the shell.  Quoting can be used to disable special treatment
       for special characters, to prevent reserved words  from        being  recog-
       nized as such, and to prevent parameter expansion.

       Each  of the metacharacters listed above under DEFINITIONS has special
       meaning to the shell and must be quoted if it is to represent  itself.

       When the command history expansion facilities are being used, the his-
       tory expansion character, usually !, must be quoted to prevent history
       expansion.

       There  are  three  quoting  mechanisms:        the  escape character, single
       quotes, and double quotes.

       A non-quoted backslash (\) is the escape character.  It preserves  the
       literal        value  of the next character that follows, with the exception
       of <newline>.  If a \<newline> pair appears, and the backslash is  not
       itself  quoted, the \<newline> is treated as a line continuation (that
       is, it is removed from the input stream and effectively ignored).

       Enclosing characters in single quotes preserves the literal  value  of
       each  character        within        the  quotes.   A  single  quote may not occur
       between single quotes, even when preceded by a backslash.

       Enclosing characters in double quotes preserves the literal  value  of
       all  characters        within the quotes, with the exception of $, ‘, and \.
       The characters $ and ‘ retain  their  special  meaning  within  double
       quotes.The backslash retains its special meaning only when followed
       by one of the following characters: $, ‘, ", \, or <newline>.  
A dou-
       ble  quote  may        be quoted within double quotes by preceding it with a
       backslash.  When command history is being used, the double  quote  may
       not be used to quote the history expansion character.


       The  special  parameters         *  and @ have special meaning when in double
       quotes (see PARAMETERS below).

       Words of the form $’string’ are treated specially.  The        word  expands
       to  string,  with backslash-escaped characters replaced as specifed by
       the ANSI C standard.  Backslash        escape        sequences,  if        present,  are
       decoded as follows:
              \a     alert (bell)
              \b     backspace
              \e     an escape character
              \f     form feed
              \n     new line
              \r     carriage return
              \t     horizontal tab
              \v     vertical tab
              \\     backslash
              \’     single quote
              \nnn   the  eight-bit  character whose value is the octal value
                     nnn (one to three digits)
              \xHH   the eight-bit character whose value is  the  hexadecimal
                     value HH (one or two hex digits)
              \cx    a control-x character

       The  expanded  result  is single-quoted, as if the dollar sign had not
       been present.

       A double-quoted string preceded by a dollar sign ($)  will  cause  the
       string  to be translated according to the current locale.  If the cur-
       rent locale is C or POSIX, the dollar sign is ignored.  If the  string
       is translated and replaced, the replacement is double-quoted.

[ 本帖最后由 ailms 于 2007-12-14 18:20 编辑 ]
作者: ailms    时间: 2007-12-14 16:32
"\\\v" 和 \\\v 的区别就是 :

前者的第1个 \ 具备 escape 功能,而第3个\由于处于 " " 中,后面不是上面红色字体提到的那4个字符($、,、"、<newline>),

所以不具备 escape 功能,也就是这个 \ 是普通字符,所以就扩展为 "\\v" 了

后者由于没有被括起来,所以第1和第3个 \ 都具备 quoting 的功能,也就是变成 \v 了

[ 本帖最后由 ailms 于 2007-12-14 16:33 编辑 ]
作者: MYSQLER    时间: 2007-12-17 10:57
学习了..感谢ailms兄..这两天有事..没上网.现在才回复.不好意思啊




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2