我必须将每行的最后一个单词替换为第一个单词。代码如下:
$ sed "s/\(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)/\1\2\1\g".
\(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)
我特别不明白这一部分\(.*\)
。
答案1
纠正基本语法错误后,您已经:
sed "s/\(^[a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)/\1\2\1/g"
s/old/new/
old
用。。。来代替new
\(^[a-z,0-9]*\)
保存行首(^
即行首)的任意数量的小写字母或数字以供日后使用(稍后使用 进行引用\1
)\(.*\)
保存任意数量的任意字符以供日后使用(引用为\2
)\([a-z,0-9]*$\)
保存行尾($
即行尾)的任意数量的小写字母或数字以供日后使用(引用为\3
)\1\2\1
打印第一个图案,然后打印第二个图案,然后再打印第一个图案g
在这个表达式中,this 是不合适的。它的意思是对同一行上的多个匹配项进行操作,但我们的表达式必须读取整行,因此g
没有意义,应该省略。
这仍然不起作用,因为正则表达式是贪婪的,所以中间\(.*\)
匹配第一个单词之后的所有内容,导致第一个单词在行尾重新打印而不替换任何内容。
您可以修复它(同时添加I
不区分大小写的搜索):
sed "s/\(^[a-z,0-9]*\) \(.*\) \([a-z,0-9]*$\)/\1 \2 \1/I"
如果您想要包含除字母和数字之外的其他字符:
sed -r 's/^([^ ]+) (.*) ([^ ]+)$/\1 \2 \1/'
-r
使用 ERE(省去使用所有反斜杠的麻烦)[^ ]+
至少一个除空格之外的任意字符
答案2
我认为您的代码在这里根本行不通,因为它的格式完全错误。我会重写整个表达式。假设所有行都以仅包含字母表中的数字和字母的单词开头和结尾,您可以尝试以下操作:
$ echo -en "foo bar baz\nThe Good, the Bad and the Ugly\n" | \
> sed 's/^\(\<[[:alpha:]]\+\>\)\(.*\)\<[[:alpha:]]\+\>$/\1\2\1/g'
foo bar foo
The Good, the Bad and the The
简要说明:
s/PATTERN/SUBSTITUTION_STRING/g
- PATTERN 是我们正在寻找的,而 SUBSTITUTION_STRING 是我们要用来替换所述模式的。g
意味着将扫描整行,而不是仅查找在该行中找到的第一个匹配项。
^\(\<[[:alpha:]]\+\>\)
- 如果一行以单词边界开头,并且后面跟着多个字母数字字符,后面跟着另一个单词边界,则将所有这些保存在变量中\1
。
\<[[:alpha:]]\+\>$
- 这里完全相同,但我们仅用它来识别最后一个单词的位置。
\(.*\)
- 其间的任何东西都将保存在变量中\2
。
\1\2\1
- 同一行,最后一个单词替换为第一个单词。