在字符串中插入字符,条件是从开头和结尾开始的字符数

时间:2015-10-16 10:56:12

标签: r regex-lookarounds

我有一个字符串列表,例如

myvar
[1] "VT" "AK" "AL2" "CA24" "NY12" 
[6] "AZ6" "WY4"

我想在所有包含3个字符的字符串中的第二个字符后插入字符“0”,并在所有包含两个字符的字符串的末尾插入“01”,以获得输出< / p>

myvar
[1] "VT01" "AK01" "AL02" "CA24" "NY12" 
[6] "AZ06" "WY04"

我以为我可以使用正则表达式前瞻和后瞻在一行中完成此操作,但我无法比这更进一步:

sub('(?<=.{2})(?=.{1})', '0', myvar, perl=T)

myvar
[1] "VT" "AK" "AL002" "CA024" "NY012" 
[6] "AZ06" "WY04"

非常感谢任何帮助,

西蒙

4 个答案:

答案 0 :(得分:6)

我们可以使用sub提取数字部分,将字符串转换为numeric类,将NA值(从强制)更改为1,并使用sprintf粘贴非数字(sub('\\d+', ...))和格式化的数字部分。

 v1 <- as.numeric(sub('\\D+', '', myvar))
 v1[is.na(v1)] <- 1
 sprintf('%s%02d', sub('\\d+', '', myvar),v1)
 #[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"

或使用gsubfn。我们为那些没有任何数字元素并粘贴1的元素创建ifelse条件。我们匹配gsubfn\\d+)中的数字部分,将其格式化为{ {1}}。

sprintf

或稍微更紧凑的版本使用 library(gsubfn) gsubfn('\\d+', ~sprintf('%02d', as.numeric(x)), ifelse(!grepl('\\d+', myvar), paste0(myvar, 1), myvar)) #[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04" 将1附加到那些没有数字部分的元素

sub

或者在没有外观的情况下使其更加紧凑,

 gsubfn('\\d+', ~sprintf('%02d', as.numeric(x)) ,sub('(?<=[A-Z])$', '1', myvar, perl=TRUE))
 #[1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"

答案 1 :(得分:5)

关于静态剪切和粘贴的想法:

paste0(substr(myvar, 0, 2), sub("00", "01", gsub(" ", "0", sprintf("% 2s", substr(myvar, 3, 4)))))

# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"

使用substr获取最后2个字符,将它们填充为2个字符,将空格替换为0,然后将00替换为01,粘贴2个第一个字符并获得结果。

一个衬垫(没有正则表达式,因为它们不需要,并且除非使用复杂的选择后再替换为什么,否则对确定替换尺寸非常有用):

myvar[nchar(myvar)<4] <- paste0(myvar[nchar(myvar)<4],sprintf(paste0("%0",4-nchar(myvar[nchar(myvar)<4]),"i"),1))

目标是获得4个字符条目的向量,因此对于4个字符(myvar[nchar(myvar)<4])下的所有条目,沿着0左边填充&#34; 1&#34;长度为4减去实际入口长度。

with可能有办法避免对myvar[nchar(myvar)<4]的多余调用,但由于我不习惯,我实际上在挖掘。

答案 2 :(得分:3)

另一种选择(可能是一个(长)班轮......):

mapply(function(x, dc_x){
           if(nchar(x)<4) paste0(dc_x[1], "0", ifelse(length(dc_x)-1, dc_x[2], "1")) else x
        }, 
       x=myvar, dc_x=strsplit(myvar,  "(?<=^.{2})", perl=T))
#    VT     AK    AL2   CA24   NY12    AZ6    WY4 
# "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04" 

<强>解释
dc_x是一个向量列表,一个用于myvar的每个元素,第一个项目是myvar中相应项目的前2个字符。因此,对于少于4个字符的元素,您将使用&#34; 01&#34;粘贴2个第一个字符。如果只有2个字符或者&#34; 0&#34;和字符串的其余部分,如果有超过2个字符。

答案 3 :(得分:2)

您可以将sub或gsub命令的输出作为输入放到另一个sub或gsub命令中。

myvar <- c("VT", "AK", "AL2", "CA24", "NY12",
           "AZ6", "WY4")
sub("^(.{2})$", "\\101", sub("^(.{2})(.)$", "\\10\\2", myvar))
# [1] "VT01" "AK01" "AL02" "CA24" "NY12" "AZ06" "WY04"