Stringのsecret_code_dataを照合するにはどうすればよいですか:
xeno://soundcloud/?code=secret_code_data#
私はもう試した
val regex = Regex("""xeno://soundcloud/?code=(.*?)#""")
field = regex.find(url)?.value ?: ""
運がなければ。疑う?コードが問題になる前に、どうにかしてエスケープする必要があります。手伝ってくれますか?
次の3つのオプションがあります。1つ目は、必要なことを行う優れた正規表現を提供し、2つ目は、URLコンポーネントのエンコード/デコードを正しく処理するRegexの代替を使用してURLを解析します。
注:Regexメソッドはほとんどのユースケースで安全ではありませんURLをコンポーネントに適切に解析せず、各コンポーネントを個別にデコードします。通常、エンコードされた一部の文字が後でRegexを混乱させる可能性があるため、URL全体を1つの文字列にデコードしてから安全に解析することはできません。これは、正規表現を使用したXHTMLの解析に似ています( ここで説明 )。以下の正規表現の代替を参照してください。
これは、より多くのURLを安全に処理する単体テストケースとしてクリーンアップされた正規表現です。この投稿の最後に、各メソッドに使用できる単体テストがあります。
_private val SECRET_CODE_REGEX = """xeno://soundcloud[/]?.*[\?&]code=([^#&]+).*""".toRegex()
fun findSecretCode(withinUrl: String): String? =
SECRET_CODE_REGEX.matchEntire(withinUrl)?.groups?.get(1)?.value
_
この正規表現は次のケースを処理します。
/
_の末尾と末尾なしKotlinで正規表現を作成する慣用的な方法は someString.toRegex()
であることに注意してください。それと他の拡張メソッドは Kotlin API Reference にあります。
KotlinのKlutterライブラリ の UriBuilder
を使用した例を次に示します。このバージョンは エンコード/デコード Java standard URI
class(which多くの問題があります)。これは安全で簡単で、特別なケースを心配する必要はありません。
実装:
_fun findSecretCode(withinUrl: String): String? {
fun isValidUri(uri: UriBuilder): Boolean = uri.scheme == "xeno"
&& uri.Host == "soundcloud"
&& (uri.encodedPath == "/" || uri.encodedPath.isNullOrBlank())
val parsed = buildUri(withinUrl)
return if (isValidUri(parsed)) parsed.decodedQueryDeduped?.get("code") else null
}
_
Klutter _uy.klutter:klutter-core-jdk6:$klutter_version
_アーティファクトは小さく、最新のURLエンコード/デコードを含む他のいくつかの拡張機能が含まれています。 (_$klutter_version
_には 最新リリース を使用します)。
このバージョンはもう少し長く、生のクエリ文字列を自分で解析し、解析後にデコードし、クエリパラメータを見つける必要があることを示しています。
_fun findSecretCode(withinUrl: String): String? {
fun isValidUri(uri: URI): Boolean = uri.scheme == "xeno"
&& uri.Host == "soundcloud"
&& (uri.rawPath == "/" || uri.rawPath.isNullOrBlank())
val parsed = URI(withinUrl)
return if (isValidUri(parsed)) {
parsed.getRawQuery().split('&').map {
val parts = it.split('=')
val name = parts.firstOrNull() ?: ""
val value = parts.drop(1).firstOrNull() ?: ""
URLDecoder.decode(name, Charsets.UTF_8.name()) to URLDecoder.decode(value, Charsets.UTF_8.name())
}.firstOrNull { it.first == "code" }?.second
} else null
}
_
これは、URIクラス自体の拡張として記述できます。
_fun URI.findSecretCode(): String? { ... }
_
すでにURIを持っているので、本文でparsed
変数を削除し、this
を使用します。次に使用して呼び出します:
_val secretCode = URI(myTestUrl).findSecretCode()
_
上記の関数のいずれかが与えられた場合、このテストを実行して機能することを証明します。
_class TestSo34594605 {
@Test fun testUriBuilderFindsCode() {
// positive test cases
val testUrls = listOf("xeno://soundcloud/?code=secret_code_data#",
"xeno://soundcloud?code=secret_code_data#",
"xeno://soundcloud/?code=secret_code_data",
"xeno://soundcloud?code=secret_code_data",
"xeno://soundcloud?code=secret_code_data&other=fish",
"xeno://soundcloud?cat=hairless&code=secret_code_data&other=fish",
"xeno://soundcloud/?cat=hairless&code=secret_code_data&other=fish",
"xeno://soundcloud/?cat=hairless&code=secret_code_data",
"xeno://soundcloud/?cat=hairless&code=secret_code_data&other=fish#fragment"
)
testUrls.forEach { test ->
assertEquals("secret_code_data", findSecretCode(test), "source URL: $test")
}
// negative test cases, don't get things on accident
val badUrls = listOf("xeno://soundcloud/code/secret_code_data#",
"xeno://soundcloud?hiddencode=secret_code_data#",
"http://www.soundcloud.com/?code=secret_code_data")
badUrls.forEach { test ->
assertNotEquals("secret_code_data", findSecretCode(test), "source URL: $test")
}
}
_
特別な意味があるため、最初の疑問符の前にエスケープを追加します
?
になる
\?
また、最初のグループのシークレットコードをキャプチャしています。ただし、後続のkotlinコードが最初のグループを抽出しているかどうかはわかりません。