理解 sed 表达式,用第一个单词替换每行的最后一个单词

理解 sed 表达式,用第一个单词替换每行的最后一个单词

我必须将每行的最后一个单词替换为第一个单词。代码如下:

$ 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- 同一行,最后一个单词替换为第一个单词。

相关内容