简体   繁体   中英

Replace odd and even occurrences of a pattern to another same pattern

Having a scenario to replace the even and odd occurrence of backslashes by the number of quotient when dividing by 2.

For example
Input: (15 backslashes)
\\\\\\\\\\\\\\\
output: (7 backslashes)
\\\\\\\

Input: (14 backslashes)
\\\\\\\\\\\\\\
output: (7 backslashes)
\\\\\\\

I tried using sed command which is working for 4 backslashes to 2. sed 's/\\\\\\\\/\\\\/g'

Appreciate if any help.

You may try this awk :

cat file

\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\

# using awk
awk '{print substr($0, 1, int(length($0)/2))}' file

\\\\\\\
\\\\\\\

Another sed solution:

$ cat ip.txt
\\\\\\\\
\\\\\\\
\\\\\\
\\\\\
\\\\
\\\
\\
\
$ sed -E 's/(\\+)\1\\?/\1/g' ip.txt
\\\\
\\\
\\\
\\
\\
\
\
\

(\\\\+)\\1\\\\? will evenly divide the backslashes, the optional matching at the end will consume the last backslash for odd cases.

If single backslash should be removed instead of being preserved, use

sed -E 's/((\\+)\2)?\\?/\2/g'

Using sed: in lines with an odd number of \\ first get rid of the last one. Then substitute pairs, as you did:

sed -r 's/((\\\\)*)(\\)?/\1/g;s/\\\\/\\/g'

Demo:

$ cat foo.txt
\\\\
\\\
\\
$ sed -r 's/((\\\\)*)(\\)?/\1/g;s/\\\\/\\/g' foo.txt
\\
\
\

With your shown samples, please try following awk code. This will work for any number of / slashes and will give half of the numbers.

awk '
BEGIN{ OFS="" }
{
  val=""
  num=split($0,arr,"")
  till=(int(num/2))
  for(i=1;i<=till;i++){
    val=(val?val OFS:"")arr[i]
  }
  print val
}
'  Input_file

Explanation: Adding detailed explanation for above.

awk '                             ##Starting awk program from here.
BEGIN{ OFS="" }                   ##Setting OFS to null here.
{
  val=""                          ##Nullifying val here.
  num=split($0,arr,"")            ##Splitting current line to arr with NULL delimiter.
  till=(int(num/2))               ##getting half of NF(number of fields) in till.
  for(i=1;i<=till;i++){           ##Traversing through fields till value of till.
    val=(val?val OFS:"")arr[i]    ##Creating val here which has array individual element value.
  }
  print val                       ##Printin val here.
}
' Input_file                      ##Mentioning Input_file name here.

Using perl, and @Sundeep's ip.txt file:

$ perl -pe 's{(\\+)}{"\\" x int(length($1)/2)}ge' ip.txt
\\\\
\\\
\\\
\\
\\
\
\

That replaces one backslash with zero backslashes.

EDITED. Try:

sed 's/\\//; s/\\\\/\\/g'

Explanation: first remove one backslash; then replace every pair with one backslash. The g at the end of the second command indicates you have to repeat the operation on whole the line. The backslashes need to be escaped. That's the reason why you write these everytime twice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM