Hapus spasi di dalam tanda kurung kecuali untuk teks dalam tanda kutip

Aug 19 2020

Saya mencari regex yang dapat menghapus spasi ketika mereka berada di antara tanda kurung yang cocok, yaitu (dan ), kecuali jika ada spasi di dalam tanda kutip ( 'atau ") di dalam tanda kurung.

Saat ini saya memiliki regex \s+(?=[^(]*\)), yang menghapus semua spasi yang ditemukan di antara tanda kurung. Begitu juga bila ada spasi di tanda petik.

// My input
do something with(in = 1, text='some text with spaces' , text2="also has spaces")

// My current output
do something with(in=1,text='sometextwithspaces',text2="alsohasspaces")

// My desired output
do something with(in=1,text='some text with spaces',text2="also has spaces")

Selanjutnya:

  • Tanda kutip hanya dapat ditemukan di dalam tanda kurung
  • Bisa ada "dalam ' 'teks:, text='text with " inside'tanpa \karakter escape.
  • Bisa ada 'dalam " "teks:, text="text with ' inside"tanpa \karakter escape.
  • Tidak ada karakter pelolosan sebelum tanda kutip dalam string:text='This is \" not there'

Saya tahu ada beberapa pertanyaan tentang pola regex, tetapi saya tidak dapat menemukan satu pun yang berhasil. Di antara banyak hal yang saya coba adalah melihat ke depan untuk hanya menemukan hal-hal di antara (sampai 'atau "dengan \s+(?=[^("]*[\)"]), tetapi masih menemukan ruang di antara "dan ".

Bisakah seseorang mengarahkan saya ke arah yang benar?

Jawaban

1 AbdessabourMtk Aug 19 2020 at 19:06

Saya membuat beberapa modifikasi pada ekspresi reguler yang Anda gunakan:

# match a space or more 
# if the fol
(?<!['"][^,]*)\s+(?=[^(]*\))|\s+(?![^,]*['"])(?=[^(]*\))

ekspresi reguler dibagi menjadi dua bagian, ekspresi reguler akan cocok dengan salah satunya:

  1. bagian pertama (?<!['"][^,]*)\s+(?=[^(]*\))cocok dengan spasi kosong sebanyak mungkin \s+yang tidak diawali dengan tanda kutip '"( (?<!['"][^,]*)) dan jika hanya diikuti dengan tanda kurung tutup.(?=[^(]*\))
  2. bagian kedua \s+(?![^,]*['"])(?=[^(]*\))cocok dengan spasi kosong sebanyak mungkin \s+yang tidak digantikan oleh kutipan (?![^,]*['"])dan hanya jika diikuti dengan tanda kurung tutup (?=[^(]*\)).

Anda bisa mengujinya di sini

2 DmitryBychenko Aug 19 2020 at 02:27

Nah, karena Anda memiliki dua jenis kutipan, "dan 'Anda harus berurusan dengan kutipan :

  abc"def pqr' ijk" "klm ' xyz"

Perhatikan bahwa kedua apostrof diberi tanda kutip dan itulah mengapa tidak berhasil. Sama dengan tanda kurung . Saya ragu apakah ekspresi reguler sederhana dapat membantu di sini, tetapi Finite State Machine dapat:

private static string RemoveSpaces(string value) {
  if (string.IsNullOrEmpty(value))
    return value;

  bool inQuotation = false;
  bool inApostroph = false;
  int bracketCount = 0;
  int escapeCount = 0;
  StringBuilder result = new StringBuilder(value.Length);

  foreach (char c in value) {
    if (inQuotation) {
      result.Append(c);
      inQuotation = c != '"' || (escapeCount % 2 != 0);
    }
    else if (inApostroph) {
      result.Append(c);
      inApostroph = c != '\'' || (escapeCount % 2 != 0);
    }
    else {
      if (c != ' ' || bracketCount <= 0)
        result.Append(c);

      if (c == '(')
        bracketCount += 1;
      else if (bracketCount == ')')
        bracketCount -= 1;

      inQuotation = c == '"' && (escapeCount % 2 == 0);
      inApostroph = c == '\'' && (escapeCount % 2 == 0);
    }

    escapeCount = c == '\\' ? escapeCount + 1 : 0;
  }
  return result.ToString();
}

Demo:

string test =
  @"do something with(in = 1, text='some text with spaces' , text2=""also has spaces"")";

Console.WriteLine(RemoveSpaces(test));

Hasil:

do something with(in=1,text='some text with spaces',text2="also has spaces")