Mam sznurek,
String s = "test string (67)";
Chcę uzyskać numer 67, który jest ciągiem między (i).
Czy ktoś może mi powiedzieć, jak to zrobić?
Odpowiedzi:
Prawdopodobnie istnieje naprawdę fajne RegExp, ale jestem noobem w tej dziedzinie, więc zamiast tego ...
String s = "test string (67)";
s = s.substring(s.indexOf("(") + 1);
s = s.substring(0, s.indexOf(")"));
System.out.println(s);
'this is an example of <how><i have it>'i muszę znaleźć wartości między '<' a '>' to
Bardzo przydatnym rozwiązaniem tego problemu, które nie wymaga od ciebie wykonania indexOf, jest użycie bibliotek Apache Commons .
StringUtils.substringBetween(s, "(", ")");
Ta metoda pozwoli ci nawet obsłużyć, nawet jeśli istnieje wiele wystąpień ciągu zamykającego, co nie będzie łatwe, szukając ciągu indexOf zamykającego.
Możesz pobrać tę bibliotekę stąd: https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.4
substringsBetween(...)jeśli spodziewasz się wielu wyników, czego szukałem. Dzięki
Spróbuj w ten sposób
String s="test string(67)";
String requiredString = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
Podpis metody dla podciągu to:
s.substring(int start, int end);
Używając wyrażenia regularnego:
String s = "test string (67)";
Pattern p = Pattern.compile("\\(.*?\\)");
Matcher m = p.matcher(s);
if(m.find())
System.out.println(m.group().subSequence(1, m.group().length()-1));
Java obsługuje wyrażenia regularne , ale są one dość kłopotliwe, jeśli faktycznie chcesz ich używać do wyodrębniania dopasowań. Myślę, że najłatwiejszym sposobem uzyskania ciągu, który chcesz w swoim przykładzie, jest użycie obsługi wyrażeń regularnych w metodzie Stringklasy replaceAll:
String x = "test string (67)".replaceAll(".*\\(|\\).*", "");
// x is now the String "67"
To po prostu usuwa wszystko, aż do pierwszego (i to samo dla )wszystkich następnych. To po prostu pozostawia zawartość między nawiasami.
Jednak wynik tego nadal jest String. Jeśli zamiast tego chcesz otrzymać wynik w postaci liczby całkowitej, musisz wykonać kolejną konwersję:
int n = Integer.parseInt(x);
// n is now the integer 67
String s = "test string (67)";
int start = 0; // '(' position in string
int end = 0; // ')' position in string
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == '(') // Looking for '(' position in string
start = i;
else if(s.charAt(i) == ')') // Looking for ')' position in string
end = i;
}
String number = s.substring(start+1, end); // you take value between start and end
Aby to zrobić, możesz użyć StringUtils biblioteki wspólnej Apache.
import org.apache.commons.lang3.StringUtils;
...
String s = "test string (67)";
s = StringUtils.substringBetween(s, "(", ")");
....
String result = s.substring(s.indexOf("(") + 1, s.indexOf(")"));
.substringuściślić twoją odpowiedź, wyjaśniając, co robi twój kod dla tych odwiedzających, którzy nie są pewni, co i .indexOf` robi.
Ciąg testowy, test string (67)z którego musisz pobrać ciąg, który jest zagnieżdżony między dwoma ciągami.
String str = "test string (67) and (77)", open = "(", close = ")";
Wymieniono kilka możliwych sposobów : Proste rozwiązanie ogólne:
String subStr = str.substring(str.indexOf( open ) + 1, str.indexOf( close ));
System.out.format("String[%s] Parsed IntValue[%d]\n", subStr, Integer.parseInt( subStr ));
Fundacja oprogramowania Apache
commons.lang3.
StringUtilsclass substringBetween()funkcja pobiera ciąg, który jest zagnieżdżony między dwoma ciągami. Zwracane jest tylko pierwsze dopasowanie.
String substringBetween = StringUtils.substringBetween(subStr, open, close);
System.out.println("Commons Lang3 : "+ substringBetween);
Zastępuje dany ciąg String, który jest zagnieżdżony między dwoma ciągami. #395
Wzorzec z wyrażeniami regularnymi:
(\()(.*?)(\)).*
The Dot zestawienia (prawie) dowolny znak
.? = .{0,1}, .* = .{0,}, .+ = .{1,}
String patternMatch = patternMatch(generateRegex(open, close), str);
System.out.println("Regular expression Value : "+ patternMatch);
Wyrażenie regularne z klasą narzędziową RegexUtilsi niektórymi funkcjami.
Pattern.DOTALL: Dopasowuje dowolny znak, w tym terminator linii.
Pattern.MULTILINE: Dopasowuje cały ciąg od początku ^do końca $sekwencji wejściowej.
public static String generateRegex(String open, String close) {
return "(" + RegexUtils.escapeQuotes(open) + ")(.*?)(" + RegexUtils.escapeQuotes(close) + ").*";
}
public static String patternMatch(String regex, CharSequence string) {
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
final Matcher matcher = pattern .matcher(string);
String returnGroupValue = null;
if (matcher.find()) { // while() { Pattern.MULTILINE }
System.out.println("Full match: " + matcher.group(0));
System.out.format("Character Index [Start:End]«[%d:%d]\n",matcher.start(),matcher.end());
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
if( i == 2 ) returnGroupValue = matcher.group( 2 );
}
}
return returnGroupValue;
}
public String getStringBetweenTwoChars(String input, String startChar, String endChar) {
try {
int start = input.indexOf(startChar);
if (start != -1) {
int end = input.indexOf(endChar, start + startChar.length());
if (end != -1) {
return input.substring(start + startChar.length(), end);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return input; // return null; || return "" ;
}
Stosowanie :
String input = "test string (67)";
String startChar = "(";
String endChar = ")";
String output = getStringBetweenTwoChars(input, startChar, endChar);
System.out.println(output);
// Output: "67"
Posługiwać się Pattern and Matcher
public class Chk {
public static void main(String[] args) {
String s = "test string (67)";
ArrayList<String> arL = new ArrayList<String>();
ArrayList<String> inL = new ArrayList<String>();
Pattern pat = Pattern.compile("\\(\\w+\\)");
Matcher mat = pat.matcher(s);
while (mat.find()) {
arL.add(mat.group());
System.out.println(mat.group());
}
for (String sx : arL) {
Pattern p = Pattern.compile("(\\w+)");
Matcher m = p.matcher(sx);
while (m.find()) {
inL.add(m.group());
System.out.println(m.group());
}
}
System.out.println(inL);
}
}
Najmniej ogólny sposób, w jaki udało mi się to zrobić z klasami Regex i Pattern / Matcher:
String text = "test string (67)";
String START = "\\("; // A literal "(" character in regex
String END = "\\)"; // A literal ")" character in regex
// Captures the word(s) between the above two character(s)
String pattern = START + "(\w+)" + END;
Pattern pattern = Pattern.compile(pattern);
Matcher matcher = pattern.matcher(text);
while(matcher.find()) {
System.out.println(matcher.group()
.replace(START, "").replace(END, ""));
}
Może to pomóc w przypadku bardziej złożonych problemów z wyrażeniami regularnymi, w których chcesz umieścić tekst między dwoma zestawami znaków.
„Ogólny” sposób polega na przeanalizowaniu ciągu od początku, odrzuceniu wszystkich znaków przed pierwszym nawiasem, zarejestrowaniu znaków po pierwszym nawiasie i wyrzuceniu znaków po drugim nawiasie.
Jestem pewien, że istnieje biblioteka wyrażeń regularnych lub coś do tego.
Innym możliwym rozwiązaniem jest użycie miejsca, w lastIndexOfktórym będzie szukał znaku lub ciągu od tyłu.
W moim scenariuszu podążałem za Stringi musiałem wydobyć<<UserName>>
1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc
Więc indexOfi StringUtils.substringBetweennie był pomocny, ponieważ zaczęli szukać postaci od początku.
Więc użyłem lastIndexOf
String str = "1QAJK-WKJSH_MyApplication_Extract_<<UserName>>.arc";
String userName = str.substring(str.lastIndexOf("_") + 1, str.lastIndexOf("."));
I to mi daje
<<UserName>>
Coś takiego:
public static String innerSubString(String txt, char prefix, char suffix) {
if(txt != null && txt.length() > 1) {
int start = 0, end = 0;
char token;
for(int i = 0; i < txt.length(); i++) {
token = txt.charAt(i);
if(token == prefix)
start = i;
else if(token == suffix)
end = i;
}
if(start + 1 < end)
return txt.substring(start+1, end);
}
return null;
}
To jest prosty \D+regex użycia i praca wykonana.
Spowoduje to wybranie wszystkich znaków z wyjątkiem cyfr, bez konieczności komplikowania
/\D+/
Zwróci oryginalny ciąg, jeśli nie pasuje do wyrażenia regularnego
var iAm67 = "test string (67)".replaceFirst("test string \\((.*)\\)", "$1");
dodaj dopasowania do kodu
String str = "test string (67)";
String regx = "test string \\((.*)\\)";
if (str.matches(regx)) {
var iAm67 = str.replaceFirst(regx, "$1");
}
---EDYTOWAĆ---
używam https://www.freeformatter.com/java-regex-tester.html#ad-output do testowania wyrażenia regularnego.
okazuje się, że lepiej dodać? po * dla mniejszego dopasowania. coś takiego:
String str = "test string (67)(69)";
String regx1 = "test string \\((.*)\\).*";
String regx2 = "test string \\((.*?)\\).*";
String ans1 = str.replaceFirst(regx1, "$1");
String ans2 = str.replaceFirst(regx2, "$1");
System.out.println("ans1:"+ans1+"\nans2:"+ans2);
// ans1:67)(69
// ans2:67
(lub znaleźć indeks pierwszego(i)i zrobić z podciąg lub, co większość ludzi zrobić, należy użyć wyrażenia regularnego.