Maybe this makes more sense, although a little bit of context would help to understand the goal.
library(tidyverse)
df %>%
separate_rows(CONCEPTS, sep = "\t") %>%
separate(CONCEPTS, into = c("Sign", "N1", "N2", "N3"), sep = "\\[|\\||\\]", extra = "drop")
#> URN QUESTION VERBATIM Sign N1 N2 N3
#> 1 A Timeliness aaa - 5 70 81
#> 2 A Timeliness aaa - 9 0 70
#> 3 B Recommendation bbb + 23 427 99
#> 4 B Recommendation bbb - 32 0 103
#> 5 B Recommendation bbb - 32 294 21
#> 6 B Recommendation bbb - 32 962 92
#> 7 B Recommendation bbb - 35 0 103
#> 8 B Recommendation bbb - 35 294 21
#> 9 B Recommendation bbb - 35 669 156
#> 10 B Recommendation bbb - 38 555 114
#> 11 B Recommendation bbb - 5 1159 103
#> 12 C Timeliness ccc - 10 0 216
#> 13 C Timeliness ccc - 32 0 216
#> 14 C Timeliness ccc - 32 216 215
#> 15 C Timeliness ccc - 48 431 84
#> 16 C Timeliness ccc - 5 431 84
#> 17 D Staff ddd - 38 0 63
#> 18 D Staff ddd - 38 176 38
#> 19 D Staff ddd - 5 95 81
#> 20 E Recommendation eee - 5 0 240
#> 21 E Recommendation eee - 9 0 240
#> 22 F Recommendation fff - 5 128 50
#> 23 G Choice Dealer ggg <NA> <NA> <NA> <NA>
#> 24 H Fixed Right First Time hhh <NA> <NA> <NA> <NA>