给定一个起始密钥令牌,后跟 n 个令牌,将 n 个令牌与密钥交错

给定一个起始密钥令牌,后跟 n 个令牌,将 n 个令牌与密钥交错

在 osx shell 中,给定一个包含这些行的流,其中第一个标记是键,该行上的第一个字符将始终匹配[a-z],其余标记将始终只是数字,它们的数量是可变的,并且只有单个空格分离令牌:

key  [1] [...] [n]
---- --------------------
key1 17 89 52
key2 5 189 6 3 5 21

如何发出以下输出(与每行上的标记数量无关)而不只是一遍又一遍地进行替换?

17 key1
89 key1
52 key1
5 key2
189 key2
6 key2
3 key2
5 key2
21 key2

(交换键和数字,或者每行保持一行由空格分隔,而不是像 那样的换行符key1 17 key1 89 key1 52,因为我可以交换标记或轻松地将它们分成多行)。

我目前正在使用sed连续替换每个下一个无钥匙号码,但这似乎效率低下,而且我必须确保我管道的sed次数多于令牌的最大数量,这可能会增加(而且确实如此,否则你猜我为什么会在这里?):

sed -E 's/^([a-z][^ ]*) ([0-9]+) /\2 \1\n\1 /g' filename.txt | sed ... | sed ...

如果我有时间去深入研究,awk我相信这会起作用。也许cut可以完成这项工作或可以有效地使用代币的其他工具之一。

您如何在代码和处理时间内有效地完成此操作?

答案1

您可以使用 awk 来实现此目的

awk '{ for(i = 2; i <= NF; i++) { print $i,$1; } }'  file

for 循环从第二个字段到最后一个字段,打印每个字段并附加第一个字段

答案2

sed非常适合这项任务。只需稍微调整一下你的 sed 代码,我们就有:

sed -E '
    s/^([a-z][^ ]*) ([0-9]+)/\2 \1\n\1/
    /\n/P;D
' filename.txt

输出:

17 key1
89 key1
52 key1
5 key2
189 key2
6 key2
3 key2
5 key2
21 key2

解释:

  • 您已经知道我从您那里获取的替代 s/// 命令,只需删除global /g flag.
  • 基本思想是,我们查看前两个元素,翻转它们,同时保存第一个元素的副本(翻转之前)并\n在翻转操作后放置一个换行符,以便我们可以使用该P命令,该命令打印直到模式空间中的第一个换行符。
  • P用a限定/\n/以避免无限循环。
  • 删除D模式空间中的第一个换行符以及模式空间的剩余部分,将控制权带回脚本的顶部。 IOW,您所做的是提供隐式循环机制。
  • 当模式空间最终被 的连续过程吃掉时,当前行的循环结束s/// --- P --- D --- s/// --- P --- D ...........
  • 之后,sed开始一个新的阅读周期,然后你就知道会发生什么了.... HTH。

相关内容