Answers:
您可以使用sed来做到这一点,是的,但是其他工具更简单。例如:
$ awk '{
printf "%s ", $2;
for(i=3;i<=NF;i++){
printf "%s:%s:1 ",$1,$(i)
}
print ""
}' file
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
AWK将分裂上的空白(默认)输入的每一行,从而节省每个字段$1
,$2
,$N
。所以:
printf "%s ", $2;
将打印第二个字段和尾随空格。 for(i=3;i<=NF;i++){ printf "%s:%s:1 ",$1,$(i) }
:将在字段3上迭代到最后一个字段(NF
是字段数),并且对于每个字段,它将打印第一个字段a :
,然后是当前字段和a :1
。print ""
:这只是打印最后的换行符。 或Perl:
$ perl -ane 'print "$F[1] "; print "$F[0]:$_:1 " for @F[2..$#F]; print "\n"' file
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
该-a
品牌perl
表现得像awk
和空格分割它的输入。在这里,这些字段存储在array中@F
,这意味着第一个字段将是$F[0]
,第二个字段$F[1]
等等。因此:
print "$F[1] "
:打印第二个字段。 print "$F[0]:$_:1 " for @F[2..$#F];
:将字段3遍历到最后一个字段($#F
是数组中元素的数量@F
,因此@F[2..$#F]
需要从第3个元素开始直到数组结尾的数组切片)并打印第一个字段a :
,然后是当前字段和a :1
。print "\n"
:这只是打印最后的换行符。这里有一个 可怕 sed
办法!
$ sed -r 's/^([0-9]+) ([0-9]+) ([0-9]+)/\2 \1:\3:1/; :a s/([0-9]+)(:[0-9]+:1) ([0-9]+)( |$)/\1\2 \1:\3:1 /; t a; s/ $//' file
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
更具可读性:
sed -r '
s/^([0-9]+) ([0-9]+) ([0-9]+)/\2 \1:\3:1/
:a
s/([0-9]+)(:[0-9]+:1) ([0-9]+)( |$)/\1\2 \1:\3:1 /
t a
s/ $//'
-r
使用EREs/old/new/
替换old
为new
^([0-9]+)
在行首保存一些数字\1
向后引用第一个保存的模式:a
标记脚本的这一部分 a
( |$)
空格或行尾t
测试最后一次替换是否成功-如果成功,则执行下一个命令a
找到标签,:a
然后再做一次s/ $//
删除尾随空格因此,在将结构添加到第一部分之后,我们反复查找结构的最后一个实例并将其应用于下一个数字...
但是我同意使用其他工具可以使工作更加轻松...
使用awk:
awk '{printf "%s ",$2; for (i=3; i<=NF; i++) printf $1":"$i":1 "; printf "\n"}' file
或使用bash:
while read -r -a a; do # read line to array a
printf "%s " ${a[1]} # print column #1
for ((i=2;i<${#a[@]};i++)); do # loop from column #2 to number of columns
printf "%s " "${a[0]}:${a[$i]}:1" # print content/values
done
echo # print line break
done < file # read file from stdin
输出:
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1 1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
好吧,您可以在sed中完成此操作,但是python也可以。
$ ./reformatfile.py input.txt
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
的内容reformatfile.py
如下:
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as fd:
for line in fd:
words = line.strip().split()
pref = words[0]
print(words[1],end=" ")
new_words = [ ":".join([pref,i,"1"]) for i in words[2:] ]
print(" ".join(new_words))
这是如何运作的?确实没有什么特别的事情发生。我们打开第一个命令行参数作为要读取的文件,然后将每一行分解为“单词”或单个项目。第一个单词变为pref
变量,然后在第二个(word [1])项目上以空格结尾的标准输出。接下来,我们通过列表理解和.join()
函数在pref,每个单词和string的临时列表上构造新的“单词”集"1"
。最后一步是将这些打印出来
与awk
:
awk '{printf("%s ", $2); for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i);\
printf("%s:%s:1\n", $1, $NF)}' file.txt
这一切都是关于将空格分隔的字段格式化为所需的格式:
printf("%s ", $2)
打印第二个字段,并在结尾加上空格
for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i)
迭代第3至最后一个字段,并以所需格式打印这些字段(第一个字段,然后是冒号,然后是当前字段,然后是冒号,最后是1),并带有尾随空格
printf("%s:%s:1\n", $1, $NF)
用换行符打印最后一个字段
例:
% cat file.txt
565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15
% awk '{printf("%s ", $2); for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i); printf("%s:%s:1\n", $1, $NF)}' file.txt
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1