^a|A$
与 ^(a|A)$
有什么区别?
感谢
答案 0 :(得分:4)
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}
import org.scalatest.FlatSpec
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
object TestProtocol {
case class Token(value: String) extends AnyVal
type Result = Future[Boolean]
}
import TestProtocol._
trait WithRefreshes {
def sinkWithRefresh(): Sink[String, Result]
def sourceWithRefresh(): Source[String, Result]
}
// code to fix / implement starts
class WithRefreshesImpl(api: Api) extends WithRefreshes {
var token: Token = Await.result(api.refreshToken(), Duration.Inf) // TODO: we want to cache tokens to avoid refreshing them again and again
override def sinkWithRefresh(): Sink[String, Result] = {
api.sink(token) // TODO: we want to refresh tokens when needed
}
override def sourceWithRefresh(): Source[String, Result] = {
api.source(token) // TODO: we want to refresh tokens when needed
}
}
// code to fix / implement ends
trait Api {
def sink(token: Token): Sink[String, Result]
def source(token: Token): Source[String, Result]
def refreshToken(): Future[Token]
}
class MockApi(data: String) extends Api {
private val expiredToken = Token("expired")
private val successfulToken = Token("ok")
private val failedToken = Token("failed")
private val refreshTokenCount = new AtomicInteger()
override def sink(token: Token): Sink[String, Result] = {
Sink.ignore.mapMaterializedValue(_ => Future.successful(token == successfulToken))
}
override def source(token: Token): Source[String, Result] = {
if (token == successfulToken) {
Source.single(data).mapMaterializedValue(_ => Future.successful(true))
} else {
Source.empty[String].mapMaterializedValue(_ => Future.successful(false))
}
}
/** Returning expired token on first invocation, then a successful token on the second one, then failed tokens for subsequent invocations*/
override def refreshToken(): Future[Token] = {
val result = refreshTokenCount.getAndIncrement() match {
case 0 => expiredToken
case 1 => successfulToken
case _ => failedToken
}
Future.successful(result)
}
}
import org.scalatest.concurrent.ScalaFutures._
import org.scalatest.Matchers._
class TestSpec extends FlatSpec {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
val data = "data"
it should "work for uploads" in {
val mockApi = new MockApi(data)
val withRefreshes = new WithRefreshesImpl(mockApi)
val sink = withRefreshes.sinkWithRefresh()
val result = Source.single("test").runWith(sink)
whenReady(result) { _ shouldEqual true }
}
it should "work for downloads" in {
val mockApi = new MockApi(data)
val withRefreshes = new WithRefreshesImpl(mockApi)
val source = withRefreshes.sourceWithRefresh()
val (result, dataF) = source.toMat(Sink.seq)(Keep.both).run
whenReady(result) { _ shouldEqual true }
whenReady(dataF) { _ shouldEqual data }
}
}
匹配以^a|A$
开头或以a
结尾的字符串。这将允许A
和abcd
作为有效字符串。
dcbA
匹配^(a|A)$
或a
字符串。此值也会捕获到一个组中,以后可以访问该组。
创建一个模式时,第一个模式通常是一个错误,该模式应检查整个字符串是否有一些变化。在这些情况下,A
和^
应始终位于更改的分组结构之外。可以使用非捕获组$
来避免捕获值。有些语言也有内置的全匹配功能,应该优先考虑那些情况(比如pythons re.fullmatch)
答案 1 :(得分:1)
^a|A$
第二选择A $ A字面匹配字符A(区分大小写) $断言字符串末尾的位置,或者在字符串末尾的行终止符之前(如果有的话)
^(A | A)$
^断言字符串开头的位置 第一捕获组(a | A) 第一选择a a字面匹配(区分大小写)
第二种选择A. A字面匹配字符A(区分大小写) $断言字符串末尾的位置,或者在字符串末尾的行终止符之前(如果有的话)