echo 1234 | sed '
/\n/ !G
s/\(.\)\(.*\n\)/&\2\1/
//D
s/.//
'
我无法理解上面的sed
代码。
我的理解是:
PATTERN SPACE=1234
first operation /\n/ !G ---> 1234\n(if \n is not found it is appended at th end)
s/\(.\)\(.*\n\)/&\2\1/ ----> 1234\n234\n1
//D ----> \n234\n1(deletes upto newline and commands
from the beginning are applied to the
existing pattern space)
PATTERN SPACE=\n234\n1
second operation /\n/ !G ---> skipped since \n234\n1 has newline now
s/\(.\)\(.*\n\)/&\2\1/ ----> \n234\n1234\n
//D ----> \n234\n1234\n
看来我做错了什么。
答案1
这段代码中有一个循环,看起来很混乱。这一点:
s/\(.\)\(.*\n\)/&\2\1/
//D
继续循环,将字符移至234\n1
,34\n21
直到剩下\n4321
,然后从循环中退出。
catonmat 的描述很准确,所以我将其放在这里:37. 反转一行(模拟“rev”Unix 命令)。。
摘抄
如果没有换行符,第一行将
"/\n/ !G"
在模式空间末尾附加换行符。第二行
"s/\(.\)\(.*\n\)/&\2\1/"
是一个简单的s///
表达式,它将第一个字符分组为 ,\1
将所有其他字符分组为\2
。然后它用 替换整个匹配的字符串"&\2\1"
,其中"&"
是整个匹配的文本 ("\1\2"
)。例如,如果输入字符串是“1234”,则s///
表达式后面的内容将变为"1234\n234\n1"
。第三行是
"//D"
。这句话是这句话的关键。空模式//
与最后一个现有的正则表达式匹配,因此它与: 完全相同/\(.\)\(.*\n\)/D
。 “D”命令从输入的开头删除直到第一个换行符,然后使用脚本中的第一个命令恢复编辑。它创建了一个循环。只要/\(.\)\(.*\n\)/
满足,sed就会恢复之前的所有操作。经过几次循环后,模式空间中的文本变为"\n4321"
。然后/\(.\)\(.*\n\)/
失败,sed 转到下一个命令。第四行
"s/.//"
删除模式空间中的第一个字符,即换行符。模式空间中的内容变为"4321"
- 的反转"1234"
。就这样,一条线被颠倒了。