使用 awk 或 python 将字符串的特定索引大写

Capitalize specific indices of string using awk or python

我有一个输入文件,其中每行包含 99 个小写字母,

bccdddcdccddddddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbcbaabbbccbb 
bccdddcdcddddcddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbcbaabbbccbb 
bccdddcdcddddccdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbccacbbbccbb 
bccdddcdccdddccdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbccaaabbccbb 

我有一个职位列表,例如p = [10, 14, 89, 99]

我想将输入文件中这些位置的字母大写。

期望的输出:

bccdddcdcCdddDddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbCbaabbbccbB 
bccdddcdcDdddCddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbCbaabbccbB 
bccdddcdcDdddCcdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbCcacbbccbbB 
bccdddcdcCdddCcdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbCcaaabbccbB 

我正在使用这个 awk 命令:

awk -vFS= -vOFS= '{=toupper()}1' input > output

但我不确定如何在所有位置上循环。

您可以使用带有 .upper()enumerate() 的生成器表达式来仅大写指定的索引:

p = [10, 14, 89, 99] # or use set([10, 14, 89, 99]) for faster lookup
with open('in.txt') as file:
    for line in file:
        line = line.rstrip()
        result = ''.join(c.upper() if i + 1 in p else c for i, c in enumerate(line))
        print(result)

这输出:

bccdddcdcCdddDddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbCbaabbbccbB
bccdddcdcDdddCddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbCbaabbbccbB
bccdddcdcDdddCcdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbCcacbbbccbB
bccdddcdcCdddCcdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbCcaaabbccbB

一个awk想法:

awk -v p="10,14,89,99" '
BEGIN { split(p,arr,",") }
      { for (i in arr)
            [=10=]=substr([=10=],1,arr[i]-1) toupper(substr([=10=],arr[i],1)) substr([=10=],arr[i]+1)
        print
      }
' input

这会生成:

bccdddcdcCdddDddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbCbaabbbccbB
bccdddcdcDdddCddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbCbaabbbccbB
bccdddcdcDdddCcdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbCcacbbbccbB
bccdddcdcCdddCcdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbCcaaabbccbB

我将利用 GNU AWK 来完成此任务,让 file.txt 内容成为

bccdddcdccddddddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbcbaabbbccbb 
bccdddcdcddddcddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbcbaabbbccbb 
bccdddcdcddddccdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbccacbbbccbb 
bccdddcdccdddccdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbccaaabbccbb

然后

awk 'BEGIN{FPAT=".";OFS="";arr[10];arr[14];arr[89];arr[99]}{for(i in arr){$i=toupper($i)};print}' file.txt

给出输出

bccdddcdcCdddDddabcdabcabdbacbdcaaccbbcabacbccabcacbcdcccbdbacdcbbcbcbcccacadaaccababadbCbaabbbccbB 
bccdddcdcDdddCddabcdabcabdbacbddaacdbbcabacbcdbbcacbcccccbdbacdbbbcbcbacbacacaacccbabadbCbaabbbccbB 
bccdddcdcDdddCcdabcdabcabdbacbddaaddbbcabacbcdbbcacbcccccbdbacdbbbcbcbaccacadaaccbbabadbCcacbbbccbB 
bccdddcdcCdddCcdabcdabcdbdbacbdcaaddcbcabacbccabcacbcdcccbdbacdbbbcbcbbccacadaaccbbabadbCcaaabbccbB

解释:我使用 FPAT 通知 GNU AWK 字段是任何单个字符并且字段分隔符是空字符串然后我提到数组 arr 的键而不关心值,因为我将只使用键。对于每一行,我遍历所述数组的键并将 tuupper 应用于这些位置,然后我 print line.

(在 GNU Awk 5.0.1 中测试)

这是使用 GNU awkFIELDWIDTHS 选项的 awk 解决方案。仅使用显示的示例编写和测试。

awk -v FIELDWIDTHS="9 1 3 1 74 1 9 1" -v OFS="" '
function toUppeR(value){
  $value=toupper($value)
}
{
  for(i=2;i<=8;i+=2){
    toUppeR(i)
  }
}
1
' Input_file

解释: 简单的解释就是,使用 GNU awkFIELDWIDTHS 选项我们可以定义字段的宽度(因此在给定的示例中我们需要将 10, 14, 89, 99 位置的字母大写,因此我将字段设置为抓住第 10 个位置(9 1 ) 赶上第14位(9 1 3 1), 赶上第89位(9 1 3 1 74 1) 等等......你可以清楚地看到它很容易在这里按位置捕获字段,尽管它可以用 OFS(输出字段分隔符)的东西,但这至少不适用于您显示的示例。