sed substitute whitespace for dash only between specific character patterns

笑着哭i 提交于 2020-01-04 05:27:10

问题


I have a lines like these:

ORIGINAL

sometext1 sometext2 word:A12 B34 C56 sometext3 sometext4
sometext5 sometext6 word:A123 B45 C67 sometext7 sometext8
sometext9 sometext10 anotherword:(someword1 someword2 someword3) sometext11 sometext12

EDITED

asdjfkklj lkdsjfic kdiw:A12 B34 C56 lksjdfioe sldkjflkjd
lknal niewoc kdiw:A123 B45 C678 oknes lkwid 
cnqule nkdal anotherword:(kdlklks inlqok mncvmnx) unqieo lksdnf

Desired output:

asdjfkklj lkdsjfic kdiw:A12-B34-C56 lksjdfioe sldkjflkjd
lknal niewoc kdiw:A123-B45-C678 oknes lkwid 
cnqule nkdal anotherword:(kdlklks-inlqok-mncvmnx) unqieo lksdnf

EDITED: Would this be more explicit? But frankly this is much more difficult to read and answer than writing sometext#. I do not know people's preference.

I only want to replace the whitespaces with dashes after A alphabet letter followed by some digits AND replace the whitespaces with dashes between the words between the two parentheses. And not any other whitespaces in the line. Would appreciate an explanation of the syntax too.

Thanks!


回答1:


This might work for you (GNU sed):

sed -r ':a;s/(A[0-9]+(-[A-Z][0-9]+)*) ([A-Z][0-9]+)/\1-\3/;ta;s/(\(\S+(-\S+)*) (\S+( \S+)*\))/\1-\3/;ta' file

Iteratively replace the space(s) in the required strings using a regexp and back references.




回答2:


This code work good

darby@Debian:~/Scrivania$ cat test.txt | sed -r 's@\s+([A-Z][0-9]+)@-\1@g' | sed ':l s/\(([^ )]*\)[ ]/\1-/;tl'
asdjfkklj lkdsjfic kdiw:A12-B34-C56 lksjdfioe sldkjflkjd
lknal niewoc kdiw:A123-B45-C678 oknes lkwid 
cnqule nkdal anotherword:(kdlklks-inlqok-mncvmnx) unqieo lksdnf

Explain my regex

In the first regex

Options

-r              Enable regex extended

Pattern

\s+             One or more space characters
([A-Z][0-9]+)   Submatch a uppercase letter and one or more digits

Replace

-              Dash character
\1             Previous submatch

Note

The g after delimiters ///g is for global substitution.

In the second regex

Pattern

:l             label branched to by t or b
tl             jump to label if any substitution has been made on the pattern space since the most recent reading of input line or execution of command 't'. If label is not specified, then jump to the end of the script. This is a conditional branch
\(([^ )]*\)    match all in round brackets and stop to first space found
[ ]            one space character

Replace

\1             Previous submatch
-              Add a dash



回答3:


You need capture the first Alphanumeric group using () and the second group. Then you can simply replace all using backreferences \1 and \2 :

using sed twice

sed -E 's/(\b[A-Za-z][0-9]+) ([A-Z])/\1-\2/g' | sed -E 's/(\b[A-Za-z][0-9]+) ([A-Z])/\1-\2/g' 

or using perl (with lookahead (?=...)the regex don't capture the 2nd group)

perl -pe 's/(\b[A-Za-z][0-9]+) (?=[A-Z])/\1-/g'


\b work boundary
[A-Za-z] 1 letter
[0-9]+ 1 or more digits

sed doesn't support lookahead and lookbehind fonctionality



来源:https://stackoverflow.com/questions/46946593/sed-substitute-whitespace-for-dash-only-between-specific-character-patterns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!