开发者

Regex for removing repeating numbers on different lines [duplicate]

开发者 https://www.devze.com 2023-04-08 05:35 出处:网络
This question already has an answer here: Reference - What does this regex mean? (1 answer) Closed 3 years ago.
This question already has an answer here: Reference - What does this regex mean? (1 answer) Closed 3 years ago.

It's perhaps quite simple, but I can't figure it out:

I have a random number (can be 1,2,3 or 4 digits) It's repeating on a second line:

2131
2131

How can I rem开发者_如何学运维ove the first number?

EDIT: Sorry I didn't explained it better. These lines are in a plain text file. I'm using BBEdit as my editor. And the actual file looks like this (only then app. 10.000 lines):

336
336
rinde
337
337
diving
338
338
graffiti
339
339
forest
340
340
mountain

If possible the result should look like this:

336 - rinde
337 - diving
338 - graffiti
339 - forest
340 - mountain


Search:

^(\d{1,4})\n(?:\1\n)+([a-z]+$)

Replace:

\1 - \2

I don't have access to BBEdit, but apparently you have to check the "Grep" option to enable regex search-n-replace. (I don't know why they call it that, since it seems to be powered by the PCRE library, which is much more powerful than grep.)


since you didn't mention any programming language, tools. I assume those numbers are in a file. each per line, and any repeated numbers are in neighbour lines. uniq command can solve your problem:

kent$  echo "1234
dquote> 1234
dquote> 431
dquote> 431
dquote> 222
dquote> 222
dquote> 234"|uniq

1234
431
222
234


Another way find: /^(\d{1,4})\n(?=\1$)/ replace: ""
modifiers mg (multi-line and global)

$str =
'1234
1234
431
431
222
222
222
234
234';

$str =~ s/^(\d{1,4})\n(?=\1$)//mg;
print $str;

Output:
1234
431
222
234

Added On the revised sample, you could do something like this:

Find: /(?=^(\d{1,4}))(?:\1\n)+\s*([^\n\d]*$)/
Replace: $1 - $2
Mods: /mg (multi-line, global)

Test:

$str =
'
336
336
rinde
337
337
337
diving
338
338
graffiti
339
337
339
forest
340
340
mountain
';

$str =~ s/(?=^(\d{1,4}))(?:\1\n)+\s*([^\n\d]*$)/$1 - $2/mg;

print $str;

Output:
336 - rinde
337 - diving
338 - graffiti
339
337
339 - forest
340 - mountain

Added2 - I was more impressed with the OP's later desired output format than the original question. It has many elements to it so, unable to control myself, generated a way too complicated regex.

Search: /^(\d{1,4})\n+(?:\1\n+)*\s*(?:((?:(?:\w|[^\S\n])*[a-zA-Z](?:\w|[^\S\n])*))\s*(?:\n|$)|)/
Replace: $1 - $2\n
Modifiers: mg (multi-line, global)

Expanded-

# Find:
s{ # Find a single unique digit pattern on a line (group 1)

   ^(\d{1,4})\n+   # Grp 1, capture a digit sequence

   (?:\1\n+)*      # Optionally consume the sequence many times,
   \s*             # and whitespaces (cleanup)

   # Get the next word (group 2)
   (?:
     # Either find a valid word
       (                      # Grp2 
          (?:
             (?:\w|[^\S\n])*     # Optional \w or non-newline whitespaces
             [a-zA-Z]            # with at least one alpha character
             (?:\w|[^\S\n])*
          )
       )
       \s*                    # Consume whitespaces (cleanup),
       (?:\n|$)               # a newline
                              # or, end of string
     |
     # OR, dont find anything (clears group 2)
   )
 }

# Replace (rewrite the new block)
 {$1 - $2\n}xmg;  # modifiers expanded, multi-line, global


find:

((\d{1,4})\r(\D{1,10}))|(\d{1,6})

replace:

\2 - \3

You should be able to clean it up from there quite easily!


Detecting such a pattern is not possible using regexp.

You can split the string by the "\n" and then compare.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号