Python 模式匹配并用if-else循环替换字符串

Python 模式匹配并用if-else循环替换字符串,python,r,awk,sed,Python,R,Awk,Sed,我有一个文件,其中包含以“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

我有一个文件,其中包含以“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
一经改变

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

谢谢

下面的代码假定
是表示文件中某行的字符串列表



如果您的输入文件与所示示例相同,请尝试以下
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.

如果您的实际输入文件与您发布的内容相同,即使在下面也可以给出所需的输出

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
    将为true,否则
    false

  • $2=$2A[++c]
    如果上述一个为真,则修改第二个字段,这样第二个字段将具有现有值加上数组
    a
    值,对应于索引(
    c
    ),
    ++c
    是增量前变量

  • !f{c=0}
    如果变量
    f
    为false,则重置变量
    c
    ,不连续

  • 1
    最后执行默认操作,即打印当前/记录/行,
    打印$0
    。要了解awk是如何工作的,请尝试,
    awk'1'infle
    ,它将打印所有记录/行,而
    awk'0'infle
    不打印任何内容。零以外的任何数字都为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
如果您想要更好的格式,如
选项卡
或其他字符作为字段分隔符,那么您可以使用下面的一个,修改
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


为什么
H74R
什么也得不到?如果H重复超过3次会发生什么?它已经有R。。。我想在“H位”(H有3位数字)模式中添加字母。删除空格并不难,但如果你能回答PoGibas的问题,这将使回答更加容易。是否总是连续出现
H\d\d
3次?H有两位数字和一个字母R就可以了,并且符合要求的命名风格。带有三位数字的H缺少R/S/T字母。。我必须添加它…它给出了错误:awk:1:意外字符“”“awk:14:意外字符“””@amruta,如果不让我知道哪些错误,我帮不了你。请告诉我错误?在Solaris/SunOS系统上也是一个猜测,将awk更改为/usr/xpg4/bin/awk、/usr/xpg6/bin/awk或nawk。我做了一些小的更改,它工作了,但没有添加R S和T字母,但这些更改没有以某种方式完成。。。很抱歉你错过了我课文的最后一部分。脚本运行了,但是没有做任何更改…我得到了输出文件,但是没有做任何更改。。作为R、S或T。我得到以下错误。文件“/test.py”,第5行,in-for-line-in-line:name错误:未定义名称“line”.我的文件名是test.dat,我将代码放入test.py。。。我是否应该将“行”改为“test.dat”?@amruta阅读我答案中的第一句话。您应该将文件中的所有行读入
。你需要帮忙吗?谢谢你的再次解释。但是现在它给了我这个错误,文件“/test.py”,第9行,在kwd=line.split()[1]indexer中,这意味着什么?这意味着输入文件中的某些行没有显示在帖子中的结构。例如,您可能有空行。我将修复代码,在一分钟内跳过这些。我没有得到任何输出。输出文件“test.log”为空。谢谢。它工作得非常好。只有一个查询。。如何设置选项卡,如下所示。。1ECLI C814 100 7.621 8.513 9.263 1ECLI H814R 101 7.607 8.617 9.289代替1ECLI C814 1007.621 8.513 9.263 1ECLI H814R 101 7.607 8.617 9.289使用
-v of s=“\t”
,和
{$1=$1}
awk将修改输出字段分隔符1ECLI C814 100 7.621 8.513 9.263 1ECLI H814R 101 7.607 8.617 9.289,而不是1ECLIC814 100 7.621 8.513 9.263 1ECLI H814R 101 7.607 8.617 9.289由于某种原因,我无法显示超前和滞后选项卡模式。您是如何尝试的?你能在评论中发布你的命令吗?为了确保OFS工作正常,你可以修改OFS='|'来测试wk-v OFS=“\t”开始{split(“R,S,t”,a,/,/)}f=$2~/^H[0-9]+$/{$2=$2A[++c]}!f{c=0}{$1=$1}1'test.in>test.out,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