sed 将所有行对齐到文件 Bash 脚本中的最后一行

sed 将所有行对齐到文件 Bash 脚本中的最后一行

我有一个包含以下行的文件

Dev_Campaign_1873.rpm
Dev_Campaign_1987.rpm
Dev_Campaign_9876.rpm
http://52.30.241.107:8081/artifactory/api/storage/adifact

尝试使用 sed 或任何其他命令将输出获取到以下文件中

http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_1873.rpm
http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_1987.rpm
http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_9876.rpm

答案1

尝试这个 sed 脚本:它非常黑客化并且依赖于两件事:文本不包含符号“|”并且只有最后一行以“http:”开头。

:again
${
s/\n/|/g
# to include first part too
s/^/|/
:next
# modify last non processed part
s/\(.*\)|\([^|]\+\)|\(.*\)\(http:.*\)/\1|\4\/\2\n\3\4/
t next
# remove unneeded guard
s/^|//
# remove prefix
s/\(.*\n\)\([^\n]\+\)/\1/
b end
}
N
b again
:end

它是如何工作的?

假设我们有这样的输入:

aaa
bbb
http://zzz

首先,脚本将文件中的所有行合并到内部缓冲区中:

:again
${
    # Here internal buffer will be processed
    b end
}
N
b again
:end

这是我的脚本中很常见的情况,当 sed 无法逐行处理文本并且输入不是很大时。从第一行开始脚本不会中断,只是将下一行(“N”)读入缓冲区直到结束。

当它到达最后一行(“$”)时,它可以继续处理。当它完成时,它停止(“b end”)。人们可以不使用明确的标签来到达结尾,只需“b”也可以,但我更喜欢清晰度。

因此,现在内部缓冲区中有这样的文本:

aaa\nbbb\nhttp://zzz

接下来它用符号“|”而不是“\n”来分隔行:

s/\n/|/g
# to include first part too
s/^/|/

|aaa|bbb|http://zzz

然后它尝试找到这个模式

...|text|.....http://...

并将其更改为

...|http://...text\n.....http://...

由于所用正则表达式的贪婪性质,替换从字符串的末尾到开头进行,每一步都会消除一个符号“|”:

Initial state of buffer:
|aaa|bbb|http://zzz

After first step:
|aaa|http://zzz/bbb\nhttp://zzz

After second step:
|http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz

循环是在命令“t next”的帮助下组织的。如果最后一次替换成功,它会跳转到标签“next”。

接下来,它删除行首不需要的保护“|”:

s/^|//

http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz

最后一行:

s/\(.*\n\)\([^\n]\+\)/\1/

http://zzz/aaa\nhttp://zzz/bbb

因此,当它最终打印缓冲区时,您将得到以下信息:

http://zzz/aaa
http://zzz/bbb

相关内容