sed切换第一个和最后一个单词的顺序

时间:2013-10-18 22:37:48

标签: regex sed

我正在尝试使用sed来切换句子中第一个和最后一个单词的顺序,因为我不认为我理解在这种情况下“贪婪”的正则表达式是多少。我只是因为三个字的句子而悲惨地失败了。

$ echo hello world mike | sed 's/\([a-z]*\).* \([a-z]*\).*/\2 \1/'
mike hello

为什么输出不是“世界你好迈克”? 一些可能有用的额外信息。

  1. \ 1 \ 2是第一个和第二个正则表达式匹配

  2. 我关注的是tutorial here

  3. 我的最终目标是切换句子中第一个和最后一个单词的顺序,而不管其中有多少个单词。

7 个答案:

答案 0 :(得分:7)

您没有将hello部分包含为您的某个捕获组,因此无法获得输出。尝试:

$ sed -E 's/([a-z]+) (.+) ([a-z]+)/\3 \2 \1/' <<< "hello world mike"
mike world hello
$ sed -E 's/([a-z]+) (.+) ([a-z]+)/\3 \2 \1/' <<< "hello world foo bar baz mike"
mike world foo bar baz hello

(注意:我也删除了您的useless use of echo。)

您也可以将[a-z]替换为[[:alpha:]]来处理大写字母:

$ sed -E 's/([[:alpha:]]+) (.+) ([[:alpha:]]+)/\3 \2 \1/' <<< "Hello world Mike"
Mike world Hello

答案 1 :(得分:2)

其他awk版本

echo hello world mike | awk '{s=$1;$1=$NF;$NF=s}1'
mike world hello

只需交换最后一次和第一次提交的文件即可。

答案 2 :(得分:2)

$ echo "hello world mike" | sed -r 's/([^ ]+)(.* )([^ ]+)/\3\2\1/'
mike world hello
$ echo "this is a simple sentence" | sed -r 's/([^ ]+)(.+ )([^ ]+)/\3\2\1/'
sentence is a simple this

或仅支持BRE的老式seds,而不是ERE:

$ echo "hello world mike" | sed 's/\([^ ]*\)\(.* \)\([^ ]*\)/\3\2\1/'
mike world hello
$ echo "this is a simple sentence" | sed 's/\([^ ]*\)\(.* \)\([^ ]*\)/\3\2\1/'
sentence is a simple this

答案 3 :(得分:1)

使用

$ echo 'hello world mike' | awk '{v1=$1;v2=$NF;$1=$NF="";print v2, $0, v1}'
mike  world  hello

答案 4 :(得分:1)

你要求交换行上的第一个和最后一个单词 - 所以你需要确保你捕获那些(而不是第一个和第二个单词,正如上面的许多答案所做的那样)。

echo "hello cruel and unkind world" | sed 's/^\([^ ]*\) \(.*\) \([^ ]*\)$/\3 \2 \1/'

将导致

world cruel and unkind hello

以下是它的工作原理:

^\([^ ]*\)  - starting at the beginning of the line (^), find as many non-space characters as you can (stops at first space)
              note - depending on the flavor of sed you use, there are special symbols to map "a non whitespace, e.g. \S
            - the next space is matched but not captured
\(.*\)      - capture "everything" after this, until...
 \([^ ]*\)$ - a space followed by all non-space characters followed by the end of string

当你以相反的顺序输出三个捕获组时,中间有一个空格,你就得到了你所要求的。

答案 5 :(得分:1)

带字边界的sed命令:

sed 's/\([A-Za-z]\+\)\(.\+\)\b\([A-Za-z]\+\)/\3\2\1/'

或在扩展模式下:

sed -r 's/([A-Za-z]+)(.+)\b([A-Za-z]+)/\3\2\1/'

答案 6 :(得分:0)

我会使用其他方法,例如更强大的语言的split(),但对于,您必须对两个边词之间的所有内容进行分组:

echo hello world mike | sed 's/\([a-z]*\)\(.*\) \([a-z]*\).*/\3\2 \1/'

它产生:

mike world hello