简体   繁体   English

使用sed替换“../../../”

[英]Replacing “../../../” using sed

I have a text file needs to edit. 我有一个需要编辑的文本文件。 The first field contains the string 第一个字段包含字符串

"../../../" “../../../”

and I want to replace with 我想替换

"/home" “/家”

. I tried using sed, but .. and / are special characters and I am a little bit stumbled how to match these patterns. 我尝试使用sed,但是..和/是特殊字符,我有点绊倒了如何匹配这些模式。 I tried using something like (..), but it seems not working for my case. 我尝试使用类似(..)的东西,但它似乎不适用于我的情况。 Could anyone help me understand how to match this kind of pattern? 谁能帮我理解如何匹配这种模式?

The . . character is considered by sed as a wildcard, so it needs to be escaped. sed将字符视为通配符,因此需要对其进行转义。 You will also need to escape the / character if you use it as a delimiter: 您还需要躲避/ 如果你用它作为分隔符:

sed 's/\.\.\/\.\.\/\.\.\//\/home/g'
#     ^                  ^      ^  <-- locations of '/' delimiters
#          ^^    ^^    ^^ ^^       <-- locations of '\/' to match literal '/' characters

The first character you provide to sed is used as the delimiter. 您为sed提供的第一个字符用作分隔符。 If your regex looks like /.../.../ or s/.../.../ then the delimiter becomes / . 如果您的正则表达式看起来像/.../.../s/.../.../那么分隔符变为/ If you replace that / delimiter with something else, then you don't need to escape the literal '/' character you're searching for (or replacing with): 如果用其他东西替换那个/分隔符,那么你不需要转义你正在搜索(或替换为)的文字'/'字符:

# Same as above, but with delimiters swapped from '/' to '@':
sed 's@\.\.\/\.\.\/\.\.\/@\/home@g'
#     ^                  ^      ^  <-- locations of '@' delimiters
#          ^^    ^^    ^^ ^^       <-- locations of '\/' to match literal '/' characters

Now with @ used as the delimiters instead of / , you can simplify/rewrite that with fewer escaped / characters: 现在使用@作为分隔符而不是/ ,您可以使用较少的转义/字符简化/重写它:

sed 's@\.\./\.\./\.\./@/home@g'
#     ^               ^     ^  <-- locations of '@' delimiters
#          ^    ^    ^ ^       <-- locations of literal '/' characters

Note: 注意:

Sadly, \\. 可悲的是, \\. isn't very readable, but necessary so you don't have this kind of edge case: 是不是很可读,但必要,所以你没有这种边缘情况:

$ echo 'ab/../cd/' | sed 's@../../../@/home@g'
/home

The above SHOULD be left unmodified: 上面应该保持不变:

$ echo 'ab/../cd/' | sed 's@\.\./\.\./\.\./@/home@g'
ab/../cd/

Slash / and dot . 斜线/. are both special regex characters to sed , so they need to be escaped if they are being used for their literal characters. sed特殊正则表达式字符,因此如果将它们用于文字字符,则需要对它们进行转义。
Dot is the single-character wildcard, so .. matches any two characters , not just a literal two-dots. Dot是单字符通配符,因此..匹配任意两个字符 ,而不仅仅是文字的两个点。
Slash delimits the search, replace, and flags, as the man page for sed states /regular expression/replacement/flags -- so your search pattern has to escape both of those, making it Slash将搜索,替换和标记分隔为sed状态/regular expression/replacement/flags手册页 - 因此您的搜索模式必须逃避这两者,使其成为

sed 's/\.\.\/\.\.\/\.\./home/g' file > newfile

That gets pretty ugly, but sed can use something other than / as the delimiter. 这变得非常丑陋,但是sed可以使用除/其他东西作为分隔符。 My favorite alternate is ~ , so the command would become 我最喜欢的替补是~ ,所以命令会变成

sed 's~\.\./\.\./\.\.~home~g' file > newfile

Update 更新
Responding to @Gu Buddy's comment... 回应@Gu Buddy的评论......

I don't know that it's "more elegant", but there are other ways to approach this. 我不知道它“更优雅”,但还有其他方法可以解决这个问题。

The special characters such as . 特殊人物如. * / lose their special meaning when used in a character class, so [.] just means period not "any char", so you can avoid escaping them * /在字符类中使用时失去其特殊含义,因此[.]只表示句点不是“任何字符”,因此可以避免转义它们

sed 's/[.][.][/]/dot-dot-slash/g' file
sed 's/[.][.][/][.][.][/][.][.]/home/g' file

You can also use a match count (repetition) — a number or range in curly-braces, applied to the char or group preceding it — but those have to be escaped unless you use extended regular expressions ("ERE" vs basic regex "BRE"), enabled via the -E flag: 您还可以使用匹配计数(重复) - 大括号中的数字或范围,应用于其前面的字符或组 - 但除非您使用扩展正则表达式 (“ERE”与基本正则表达式“BRE”),否则必须对其进行转义“),通过-E标志启用:

    sed 's~\([.][.][/]\)\{3\}~home/~' file  # with BRE
group start-^  grp end-^  ^-count
    sed -E 's~([.][.][/]){3}~home/~' file   # with ERE
    sed -E 's~([.]{2}[/]){3}~home/~' file   # also ERE

Notice in my original answer I avoided replacing the third slash, leaving it there to separate the replacement "home" from the remaining path... 请注意,在我原来的答案中,我避免更换第三个斜线,将其留在那里将替换“主页”与剩余路径分开......

../../../
        ^

...but using the repetition of {3} it will match and replace that third slash, so I have to include the slash after home in the replacement string. ...但是使用重复的{3}它将匹配并替换第三个斜杠,所以我必须在替换字符串中包含home之后的斜杠。

I tested all of these on a file that just contains this: 我在一个只包含此文件的文件中测试了所有这些:

../../../this/that/file.txt
../../../some/otherfile.txt

getting this output: 得到这个输出:

home/this/that/file.txt
home/some/otherfile.txt

你需要逃避斜线和点:

sed 's/\.\.\/\.\.\/\.\./\/home/g' file.txt > newfile.txt

We can use regex to get the desired output. 我们可以使用正则表达式来获得所需的输出。

echo "../../../" | sed -r 's/(..\/){3}/\/home/g'

Option Detail 选项细节

According to man page of sed 根据sed man page

-E, -r, --regexp-extended -E,-r, - regexp-extended

use extended regular expressions in the script (for portability use POSIX -E). 在脚本中使用扩展的正则表达式(为了便携性使用POSIX -E)。

REGEX Details REGEX详细信息

(../){3} : It will provide "../../../" (../) {3} :它将提供“../../../”

As we are using (/) in sed ex. 因为我们在sed ex中使用(/) sed 's///g' so we can not use normal (/) in sed so we need to escape this character by (/) sed的/// g'所以我们不能在sed中使用普通(/)所以我们需要通过(/)来转义这个字符

As this is to specific to (../) 3 times. 因为这是特定的(../)3次。 If you want to change all (../) add * in place of {3}. 如果你想改变所有(../)add *代替{3}。 ex. 恩。 (../)* (../)*

/home : It gives "/home" / home:它给出了“/ home”

If you want one more (/) after home you can add (/home/) 如果你想再回家一次(/)你可以添加(/ home /)

sed -r 's/ (../){3} / /home /g' sed -r's (../){3} / /home / g'

So we are just substituting "/home" in place of "../../../". 所以我们只是用“/ home”代替“../../../”。 Now, you can change it as per your need. 现在,您可以根据需要进行更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM