【问题标题】:How to clean a string and leave in place only the first semicolon如何清理字符串并仅保留第一个分号
【发布时间】:2018-05-05 04:59:21
【问题描述】:

我在 CSV 文件中有这样的列表:

    4231;"Swiss Federal Railways (SBB; CFF; FFS)"
    67;"Hershey Co; The"

我的目标是清除这些字符串并只保留第一个分号:

4231; Swiss Federal Railways (SBB CFF FFS)
67; Hershey Co The

我尝试过这样做:

String[] companyDetails =
                    line.replaceAll("\"","").trim().split(";");

但这还不够。

编辑: 更清楚地说,这是我使用的代码:

br = new BufferedReader(new FileReader("/Users/blue/IdeaProjects/matching/src/main/resources/company_list.csv"));

            // Creating a HashSet for holding Company object
            HashSet<Company> companyHashSet = new HashSet<Company>();

            String line;

            // Read to skip the header
            br.readLine();

            // Reading from second line
            while ((line = br.readLine()) != null) {

                String[] companyDetails =
                        line.replaceAll("\"","").trim().split(";");

【问题讨论】:

  • 我不知道这在 Java 中是否可行(仅使用正则表达式),因为它的正则表达式引擎不包含其他正则表达式引擎所做的某些标记。在其他正则表达式风格中,您可以使用(?:^[^;\v]*;|\G(?!\A))[^;\v]*\K;
  • 您还没有替换其他分号。这与替换语音标记的协议完全相同,只是您使用正则表达式先在语音标记内部查找分号,然后将其删除
  • 也许从第一个分号中获取一个子字符串,然后执行你的 replaceAll 方法。

标签: java regex csv


【解决方案1】:

在 java 中,您可以使用 split() 函数:每次找到模式时,它都会将字符串分解为一个数组。 在你的情况下:

    String source = "4231;\"Swiss Federal Railways (SBB; CFF; FFS)\"";
    String parts[] = source.split(";");
    String fullString = "";
    for (int i = 0; i < parts.length; i++)
        if (i != 0) fullString = fullString + parts[i];
    fullString = parts[0] + ";" + fullString;

然后根据需要构建最终的字符串

【讨论】:

  • 嗨,Marco,这是不正确的。我的目的是维护第一个分号,而不是全部替换
  • 这样,您将第一个字符串分成几部分,然后对其进行操作。我只是一个可能的解决方案的提示,我已经看到了 ctwheels 的答案,它更优雅但也更复杂,这取决于你必须做什么。
  • Grazie Marco del tuo aiuto, proverò ad utilizzare il tuo metodo(forse sei italiano come me)。谢谢Marco的帮助,我会尽量用你的方法(可能你和我一样是意大利人)
【解决方案2】:

代码

Java

See regex in use here

((?:^[^;\v]*;|\G(?!\A))[^;\v]*);

替换

$1

其他语言(即 PCRE)

在其他正则表达式风格中,您可以使用以下正则表达式,但 Java 不支持标记 \K(重置报告匹配的起点 - 任何先前使用的字符都不再包含在最终匹配中)。这将使用空字符串替换而不是捕获组。

(?:^[^;\v]*;|\G(?!\A))[^;\v]*\K;

用法

See code in use here

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "((?:^[^;\\v]*;|\\G(?!\\A))[^;\\v]*);";
final String string = "    4231;\"Swiss Federal Railways (SBB; CFF; FFS)\"\n"
     + "    67;\"Hershey Co; The\"";
final String subst = "$1";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);

结果

输入

     4231;"Swiss Federal Railways (SBB; CFF; FFS)"
     67;"Hershey Co; The"

输出

     4231;"Swiss Federal Railways (SBB CFF FFS)"
     67;"Hershey Co The"

说明

  • ((?:^[^;\v]*;|\G(?!\A))[^;\v]*) 将以下内容捕获到捕获组 1
    • (?:^[^;\v]*;|\G(?!\A)) 匹配以下任意一项
      • ^[^;\v]*;
        • ^ 在行首断言位置
        • [^;\v]* 匹配集合中不存在的任意数量的任意字符(除分号 ; 或垂直空格以外的任意字符)
        • ; 匹配分号字符 ; 字面意思
      • \G(?!\A)在上一场比赛结束时断言位置
    • [^;\v]* 匹配集合中不存在的任意数量的任意字符(除分号 ; 或垂直空格之外的任意字符)
  • ; 匹配分号字符 ; 字面意思

【讨论】:

  • 很棒的正则表达式解释! @OP:将该解释作为注释复制到您的源代码中。未来的读者会庆幸他们不必花费数小时试图理解正则表达式背后的逻辑。
  • @ctwheels:如何将您的结果与我的情况合并?
  • @StoreCode 你基本上会用line 替换string 变量
  • @ctwheels:对不起,我不能br = new BufferedReader(new FileReader("/Users/blue/IdeaProjects/matching/src/main/resources/company_list.csv")); // Creating a HashSet for holding Company object HashSet&lt;Company&gt; companyHashSet = new HashSet&lt;Company&gt;(); String line; br.readLine(); // Reading from second line while ((line = br.readLine()) != null) { String[] companyDetails = line.replaceAll("\"","").trim().split(";");
  • 如何在我的解决方案之间合并
【解决方案3】:

您可以替换第一次出现的 ;使用临时字符串,进行更改,然后将临时部分恢复为分号。

String s = "4231;\"Swiss Federal Railways (SBB; CFF; FFS)\"";
s = s.replaceFirst(";", "~~~").replaceAll(";", "").replaceAll("\"", "").replaceFirst("~~~", "; ");
System.out.println(s);

输出:

4231; Swiss Federal Railways (SBB CFF FFS)

【讨论】:

  • 这不起作用,我的解决方案有错误。
  • @StoreCode 你能发布错误吗?它对我有用
  • 它说需要 java.lang.String[] 但发现:java.lang.String
  • 在本例中,我没有使用拆分,因此字符串保持为字符串类型。输出不是字符串数组。所以你需要String companyDetails = ... 而不是String[] companyDetails = ... 因此:String companyDetails = line.replaceFirst(";", "~~~").replaceAll(";", "").replaceAll("\"", "").replaceFirst("~~~", "; ");
  • 但是不行,之后实现就是放入hashSet,我试试
猜你喜欢
  • 1970-01-01
  • 2023-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 1970-01-01
相关资源
最近更新 更多