是否可以将另一个字符串之后以 # 开头的字符串移动到前一行?

是否可以将另一个字符串之后以 # 开头的字符串移动到前一行?

我有一个如下所示的脚本文件:

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 ....

相关内容