import Foundation
// WARNING: You included a flag that Swift doesn't support: J
// Wehn this flag is set, it allows duplicated capturing group names.
// By default, Swift captures only the last value matched for a repeated capture group.
// As an alternative, the pattern can be modified to contain one capturing group per group you want to get in the result.
let pattern = ##"""
(?:(?<=^\n)|(?<=\A))
(?<table>
(?<table_caption>(?&t_caption))? # maybe some caption at the top?
(?<table_headers>
(?<table_header> # Table header
(?<table_header_sep_top>(?&t_th_sep))? # Possible top separator line
(?<table_header1> # First header row
[^\n]+\n
)
(?<table_header_sep>(?&t_th_sep)) # a separator
(?<table_header2> # and possibly a second row of header
[^\n]+\n
(?<table_header_sep>(?&t_th_sep))
)?
)
)
(?<table_rows> # Multiple table rows
(?<table_row>(?&t_row))*
)
(?<table_bottom_sep>(?&t_th_sep))? # Possibly ended by a separator line
(?<table_caption>(?&t_caption))? # and maybe with some caption at the bottom
(?=\n|\Z)
)
(?(DEFINE)
(?<t_th_sep>
[\+\-\|](?:[\: ]*\-+[\: ]*[\+\-\|]?)+\n
)
(?<t_row>
[ ]{0,3}
(?!(?&t_th_sep)|(?&t_caption))
(?:
(?<tr_start_mark>[\|\:]+)?
(?<tr_col_content>[^\|\:\n]+)
(?:
(?:[\|\:]{0,2}[ ]*(?=\n))
|
[\|\:]{1,2}
)
)+
(?:
(?:\n(?=(?&t_th_sep)))
|
(?:\n(?=(?&t_caption)))
|
\n
)
)
(?<t_caption>
[ ]{0,3}
\[[^\]]+\]
[ ]*
\n
)
)
"""##
let regex = try! NSRegularExpression(pattern: pattern, options: [.anchorsMatchLines, .allowCommentsAndWhitespace])
let testString = ##"""
| | Grouping ||
+---------------+---------------------------------+
| First Header | Second Header | Third Header |
+---------------+-----------------+---------------+
| Content | *Long Cell* ||
: continued : ::
: content : ::
| Content | **Cell** | Cell |
: continued : : :
: content : : :
| New section | More | Data |
| And more | And more ||
[Prototype table]
Header 1 | Header 2
--------- | ---------
Cell 1 | Cell 2
Cell 3 | Cell 4
With leading pipes:
| Header 1 | Header 2
| --------- | ---------
| Cell 1 | Cell 2
| Cell 3 | Cell 4
With tailing pipes:
Header 1 | Header 2 |
--------- | --------- |
Cell 1 | Cell 2 |
Cell 3 | Cell 4 |
With leading and tailing pipes:
| Header 1 | Header 2 |
| --------- | --------- |
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |
* * *
# One-column one-row table
With leading pipes:
| Header
| -------
| Cell
With tailing pipes:
Header |
------- |
Cell |
With leading and tailing pipes:
| Header |
| ------- |
| Cell |
* * *
Table alignement:
| Default | Right | Center | Left |
| --------- |:--------- |:---------:| ---------:|
| Long Cell | Long Cell | Long Cell | Long Cell |
| Cell | Cell | Cell | Cell |
Table alignement (alternate spacing):
| Default | Right | Center | Left |
| --------- | :-------- | :-------: | --------: |
| Long Cell | Long Cell | Long Cell | Long Cell |
| Cell | Cell | Cell | Cell |
* * *
# Empty cells
| Header 1 | Header 2 |
| --------- | --------- |
| A | B |
| C | |
Header 1 | Header 2
--------- | ---------
A | B
| D
* * *
# Missing tailing pipe
Header 1 | Header 2
--------- | --------- |
Cell | Cell |
Cell | Cell |
Header 1 | Header 2 |
--------- | ---------
Cell | Cell |
Cell | Cell |
Header 1 | Header 2 |
--------- | --------- |
Cell | Cell
Cell | Cell |
Header 1 | Header 2 |
--------- | --------- |
Cell | Cell |
Cell | Cell
* * *
# Too many pipes in rows
| Header 1 | Header 2 |
| ---------
| Cell | Cell | Extra cell? |
| Cell | Cell | Extra cell? |
"""##
let stringRange = NSRange(location: 0, length: testString.utf16.count)
let matches = regex.matches(in: testString, range: stringRange)
var result: [[String]] = []
for match in matches {
var groups: [String] = []
for rangeIndex in 1 ..< match.numberOfRanges {
let nsRange = match.range(at: rangeIndex)
guard !NSEqualRanges(nsRange, NSMakeRange(NSNotFound, 0)) else { continue }
let string = (testString as NSString).substring(with: nsRange)
groups.append(string)
}
if !groups.isEmpty {
result.append(groups)
}
}
print(result)
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Swift 5.2, please visit: https://developer.apple.com/documentation/foundation/nsregularexpression