我有一个包含多行以“1ECLI H --- 12.345 .....”开头的文件。我想删除I和H之间的空格,并在迭代H模式时添加R / S / T.例如。 H810如果连续三行重复,则应加上字母R,S(第二次迭代),T(第三次迭代)。所以它将是H810R。任何帮助将不胜感激 文字如下所示
1ECLI H813 98 7.529 8.326 9.267
1ECLI H813 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814 101 7.607 8.617 9.289
1ECLI H814 102 7.633 8.489 9.156
1ECLI H814 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
on chage
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814s 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
感谢。
答案 0 :(得分:2)
如果您的Input_file与显示的示例相同,那么您可以尝试关注awk
并告诉我这是否对您有帮助。
awk '
BEGIN{
val[1]="R";
val[2]="S";
val[3]="T"
}
$2 !~ /^H[0-9]+/ || i==3{
i=""
}
$2 ~ /^H[0-9]+$/ && /^1ECLI/{
$2=$2val[++i]
}
1
' Input_file > temp_file && mv temp_file Input_file
也可以通过以下方式添加解释。
awk '
BEGIN{ ##Starting BEGIN section of awk here.
val[1]="R"; ##creating an array named val whose index is 1 and value is string R.
val[2]="S"; ##creating array val 2nd element here whose value is S.
val[3]="T" ##creating array val 3rd element here whose value is T.
}
$2 !~ /^H[0-9]+/ || i==3{ ##Checking condition if 2nd field does not start from H and digits after that OR variable i value is equal to 3.
i="" ##Then nullifying the value of variable i here.
}
$2 ~ /^H[0-9]+$/ && /^1ECLI/{ ##Checking here if 2nd field value is starts from H till all digits till end AND line starts from 1ECLI string then do following.
$2=$2val[++i] ##re-creating value of 2nd field by adding value of array val whose index is increasing value of variable i.
}
1 ##Mentioning 1 here, which means it will print the current line.
' Input_file > temp_file && mv temp_file Input_file ##Mentioning Input_file name here.
答案 1 :(得分:1)
如果您的真实输入文件与您发布的文件相同,即使低于一个也可以提供所需的输出。
awk 'BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}1' infile
<强>解释强>
split("R,S,T",a,/,/)
- 按分隔符逗号分割字符串"R,S,T"
,并保存在数组a
中,因此它变为a[1] = R, a[2] = S, a[3] = T
f=$2~/^H[0-9]+$/
- f
是变量,验证regexp $2 ~ /^H[0-9]+$/
,返回布尔状态。如果它返回true
,那么变量f
将为真,否则false
$2 = $2 a[++c]
如果上面的一个为真,则修改第二个字段,因此第二个字段将具有现有值加上数组a
值,对应于索引(c
), ++c
是预增量变量
!f{c=0}
如果变量f
为false,则重置变量c
,而不是连续。
1
执行默认操作,即打印当前/记录/行,print $0
。要知道awk如何工作,请尝试awk '1' infile
,它将打印所有记录/行,而awk '0' infile
则不打印任何内容。除零以外的任何数字都是 true ,这会触发默认行为。
测试结果:
$ cat infile
1ECLI H813 98 7.529 8.326 9.267
1ECLI H813 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814 101 7.607 8.617 9.289
1ECLI H814 102 7.633 8.489 9.156
1ECLI H814 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
$ awk 'BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}1' infile
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814S 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
如果您希望更好地格式化tab
或其他字符作为字段分隔符,那么您可以使用下面一个,修改OFS
变量
$ awk -v OFS="\t" 'BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}{$1=$1}1' infile
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814S 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
答案 2 :(得分:0)
以下代码假定lines
是表示文件中一行的字符串列表。
with open('filename') as f:
lines = f.readlines()
from collections import defaultdict
cntd = defaultdict(lambda: 0)
suffix = ['R', 'S', 'T']
newlines = []
for line in lines:
try:
kwd = line.split()[1]
except IndexError:
newlines.append(line)
continue
if kwd[0] == 'H' and kwd[-1].isdigit():
sfx = suffix[cntd[kwd]]
idx = line.index(kwd)
nl = line[:idx -1] + kwd + sfx + line[idx + len(kwd):]
# nl = line[:idx + len(kwd)] + sfx + line[idx + len(kwd):] # adjust formatting to your taste
newlines.append(nl)
cntd[kwd] += 1
else:
newlines.append(line)
with open('filename', 'w') as f:
f.writelines(newlines)