我有一个如下所示的脚本文件:
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000 <TAB> #description of command....
auditctl -a .... <TAB> #long description
(注意注释前的制表符。)
可以使用sed
、 或awk
、 或vim
内部命令将描述放在#
字符串本身之后,这样我将获得如下所示的内容:
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....
我尝试过这个norm
命令,但结果是一场灾难
:'<,'>norm f#D O P
答案1
使用 GNU awk 作为第三个参数 tomatch()
和\S/\s
简写:
$ awk 'match($0,/([^#]*\S)\s*(#.*)/,a) { $0=a[2] ORS a[1] } 1' file
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....
或使用任何 POSIX awk:
$ awk 'match($0,/[[:space:]]*#/) { $0=substr($0,RSTART+RLENGTH-1) ORS substr($0,1,RSTART-1) } 1' file
#description of # command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....
请注意,无论注释包含哪些字符(包括 a ),#
以及注释之前是否有空格,上面的代码都将起作用,并且它会在打印之前从行的其余部分的末尾去除所有注释前的空格。
答案2
使用sed
,可以使用反向引用来匹配模式:
sed 's/\(PATTERN1\)\(PATTERN2\)/\2\n\1/'
将反转两个模式并在中间添加换行符。 PATTERN1 可以是例如^.*
从行开头开始的任何字符,PATTERN2#.*$
可以是散列符号,后跟任意数量的字符直到行尾。
要删除多余的空格,可能需要添加以下内容:
's/ *$//'
#
最好还通过 排除第一部分匹配中的字符[^#]
(即任何不是 NOT 的字符)来处理自己文本中的注释#
。结合起来,这使得:
sed 's/\(^[^#]*\)\(#.*$\)/\2\n\1/;s/ *$//'
答案3
以下awk
程序应该执行以下操作:
awk '/^ *[^ #].+#/{n=index($0,"#"); print substr($0,n); $0=substr($0,1,n-1)}1' input.sh
这将执行以下操作
- 我们确保只处理第一个字符(可能在前导空格之后)是的行不是符号
#
,即确保这是命令之后的注释,而不是“纯注释”行。 - 如果我们在这样的线上,确定第一条线的位置
#
并将其存储在n
.然后我们将当前行的子字符串从该位置开始打印在单独的一行上。然后,我们仅用 . 之前的部分“覆盖”当前行#
。这种方法甚至可以处理注释部分本身包含该#
字符的情况。 1
对于所有行,我们都会打印它们,包括可能进行的任何修改(这就是规则块之外看似“杂散”的含义)。
请注意,它awk
不会执行文件的就地编辑,因此您必须将输出重定向到临时文件。或者,如果您有 GNU Awk 4.1.0 或更高版本,则可以使用该-i inplace
扩展进行真正的就地编辑。
答案4
我喜欢这种rev
方法,例如 @Ed Morton 指出的替代案例:
输入文件示例:
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000 #description of command....
auditctl -a .... #long description
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000#description of command....
auditctl -a .... #long description# foo
auditctl -a .... # long description#foo
$ rev file | sed 's/^\(.*\)#[[:blank:]]*/\1#\n/' | rev
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description# foo
auditctl -a ....
# long description#foo
auditctl -a ....