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

Viewed 187

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.

6 Answers

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.

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.

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.

Related