matches.find()与replaceAll()

时间:2018-03-01 04:18:38

标签: java regex

我是Java的新手,我在现有代码中找到了一个循环,看起来它应该是一个无限循环(或者具有非常不受欢迎的行为),它实际上有效。

你能解释一下我错过了什么吗?我认为它应该是无限的原因是,根据这里的文档(https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#replaceAll-java.lang.String-),对replaceAll的调用将重置匹配器(此方法首先重置此匹配器。然后它扫描输入序列...... )。所以我认为下面的代码会替换它,然后再次调用find(),这将从头开始。并且它将继续查找相同的字符串,因为您可以看到字符串刚刚被包裹在标记中。

如果不明显,Pattern和Matcher是java.util.regex中的类。

String aTagName = getSomeTagName()
String text = getSomeText()
Pattern pattern = getSomePattern()
Matcher matches = pattern.matcher(text);
while (matches.find()) {
    text = matches.replaceAll(String.format("<%1$s> %2$s </%1$s>", aTagName, matches.group()));
}

为什么不是这样?

2 个答案:

答案 0 :(得分:1)

我怀疑此代码很可能是无意的,因为import tensorflow as tf # Function in python def dummy(x): return [x,x] print(dummy([1.0,2.0])) tf_fun = tf.py_func(dummy,[[1.0,2.0]],(tf.float32,tf.float32)) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run(tf_fun)) 更改了状态,并且由于它扫描要替换的字符串,结果是仅执行1次搜索并且声明的群组用于替换此群组的所有搜索

replaceAll

String text = "abcdEfg"; Pattern pattern = Pattern.compile("[a-z]"); Matcher matches = pattern.matcher(text); while (matches.find()) { System.out.println(text); // abcdEfg text = matches.replaceAll(matches.group()); System.out.println(text); // aaaaEaa } 告诉匹配器扫描字符串时,它最终将指针移动到末尾以耗尽整个字符串的状态。然后replaceAll恢复搜索(从当前状态 - 这是结束,而不是开始),但搜索已经用尽。

适当地迭代和替换每个组的正确方法之一可能是使用find

appendReplacement

答案 1 :(得分:1)

以下示例显示如果您使用全部替换,则没有理由调用while循环。在这两种情况下,答案都是

夏天? 炎热的夏天。 不是吗?

function New-SWRandomPassword {
    [CmdletBinding(DefaultParameterSetName='FixedLength',ConfirmImpact='None')]
    [OutputType([String])]
    Param
    (
        # Specifies minimum password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='RandomLength')]
        [ValidateScript({$_ -gt 0})]
        [Alias('Min')] 
        [int]$MinPasswordLength = 8,

        # Specifies maximum password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='RandomLength')]
        [ValidateScript({
                if($_ -ge $MinPasswordLength){$true}
                else{Throw 'Max value cannot be lesser than min value.'}})]
        [Alias('Max')]
        [int]$MaxPasswordLength = 11,

        # Specifies a fixed password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='FixedLength')]
        [ValidateRange(1,2147483647)]
        [int]$PasswordLength = 10,

        # Specifies an array of strings containing charactergroups from which the password will be generated.
        # At least one char from each group (string) will be used.
        [String[]]$InputStrings = @('abcdefghijkmnpqrstuvwxyz', 'ABCEFGHJKLMNPQRSTUVWXYZ', '23456789', '!"#%&'),

        # Specifies a string containing a character group from which the first character in the password will be generated.
        # Useful for systems which requires first char in password to be alphabetic.
        [String] $FirstChar,

        # Specifies number of passwords to generate.
        [ValidateRange(1,2147483647)]
        [int]$Count = 1
    )
    Begin {
        Function Get-Seed{
            # Generate a seed for randomization
            $RandomBytes = New-Object -TypeName 'System.Byte[]' 4
            $Random = New-Object -TypeName 'System.Security.Cryptography.RNGCryptoServiceProvider'
            $Random.GetBytes($RandomBytes)
            [BitConverter]::ToUInt32($RandomBytes, 0)
        }
    }
    Process {
        For($iteration = 1;$iteration -le $Count; $iteration++){
            $Password = @{}
            # Create char arrays containing groups of possible chars
            [char[][]]$CharGroups = $InputStrings

            # Create char array containing all chars
            $AllChars = $CharGroups | ForEach-Object {[Char[]]$_}

            # Set password length
            if($PSCmdlet.ParameterSetName -eq 'RandomLength')
            {
                if($MinPasswordLength -eq $MaxPasswordLength) {
                    # If password length is set, use set length
                    $PasswordLength = $MinPasswordLength
                }
                else {
                    # Otherwise randomize password length
                    $PasswordLength = ((Get-Seed) % ($MaxPasswordLength + 1 - $MinPasswordLength)) + $MinPasswordLength
                }
            }

            # If FirstChar is defined, randomize first char in password from that string.
            if($PSBoundParameters.ContainsKey('FirstChar')){
                $Password.Add(0,$FirstChar[((Get-Seed) % $FirstChar.Length)])
            }
            # Randomize one char from each group
            Foreach($Group in $CharGroups) {
                if($Password.Count -lt $PasswordLength) {
                    $Index = Get-Seed
                    While ($Password.ContainsKey($Index)){
                        $Index = Get-Seed                        
                    }
                    $Password.Add($Index,$Group[((Get-Seed) % $Group.Count)])
                }
            }

            # Fill out with chars from $AllChars
            for($i=$Password.Count;$i -lt $PasswordLength;$i++) {
                $Index = Get-Seed
                While ($Password.ContainsKey($Index)){
                    $Index = Get-Seed                        
                }
                $Password.Add($Index,$AllChars[((Get-Seed) % $AllChars.Count)])
            }
            Return $(-join ($Password.GetEnumerator() | Sort-Object -Property Name | Select-Object -ExpandProperty Value))
        }
    }
}

New-SWRandomPassword