Home > Net >  File Formatting with sed
File Formatting with sed

Time:06-24

I've been trying to manipulate a single line in a file without much success.

test.txt

10.20.30.40 "User 1"
73.15.16.24 NewUser
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"

If you notice the second line doesn't have quotes around the last word. I have been trying to figure out a way to put quotes around that and save it, either in another file, or preferably in the original.

When I used this command:

cat test.txt | grep -v '".*"' | sed -i 's/\([A-Z]\)/"\1/g'

It finds the correct line and places a quote at the beginning of the word, but then puts another before the U, which isn't what I need. I could always use sed to place a quote at the last position of course, but it would be nice to encompass the entire word.

If I then use the sed command with the -i and point it to the original file, it then throws quotes around every word when saved, which is also what I'm not wanting.

Any help is appreciated, I've been trying to solve this for a couple of days now.

CodePudding user response:

Using sed

$ sed -i.bak '/"/!{s/[[:alpha:]]\ \( \S\ \)\?$/"&"/}' input_file
10.20.30.40 "User 1"
73.15.16.24 "NewUser"
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"

-i will allow you to save your file in place

.bak will create a backup of the original with .bak extension

CodePudding user response:

You can use

sed -E 's/^([0-9] (\.[0-9] ){3})[[:space:]] ([^[:space:]"] )$/\1 "\3"/' file > newfile

With GNU sed:

sed -i -E 's/^([0-9] (\.[0-9] ){3})\s ([^[:space:]"] )$/\1 "\3"/' file

Details:

  • ^ - start of string
  • ([0-9] (\.[0-9] ){3}) - one or more digits and then 3 occurrences of . and one or more digits
  • [[:space:]] - one or more whitespaces
  • ([^[:space:]"] ) - Group 3: one or more chars other than " and whitespace
  • $ - end of string.

See the online demo:

#!/bin/bash
s='10.20.30.40 "User 1"
73.15.16.24 NewUser
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"'

sed -E 's/^([0-9] (\.[0-9] ){3})[[:space:]] ([^[:space:]"] )$/\1 "\3"/' <<< "$s"

Output:

10.20.30.40 "User 1"
73.15.16.24 "NewUser"
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"

CodePudding user response:

A pure bash solution which may be a little easier to read and maintain than sed:

#!/bin/bash
# read each line of the file into an array
while read -ra line ; do
  # "user" is everything after the first token in the line
  user="${line[*]:1}"
  # if user isn't surrounded by quotes then add them,
  # otherwise just print the line verbatim
  if [[ "${user}" != \"*\" ]] ; then
    echo "${line[0]} \"${user}\""
  else
    echo "${line[@]}"
  fi
done < test.txt > test.txt.new
# Put the edited file back in place over top of
# the original file. Start off commented in case
# you want to diff before overwriting the original.
# mv test.txt.new test.txt

CodePudding user response:

Using awk:

awk '{print (NR==2) ?  $1 " \"" $2 "\"" : $0}' inputfile

Output:

10.20.30.40 "User 1"
73.15.16.24 "NewUser"
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"

Or a bit more generic using a regex:

awk '{ print ($2 ~ /\"*\"/) ? $0 : $1 " \"" $2 "\""}' t.dat

Output:

10.20.30.40 "User 1"
73.15.16.24 "NewUser"
124.18.21.17 "User 2"
27.76.58.248 "User 3"
39.16.87.227 "User 4"
211.129.20.52 "User 5"
175.15.118.110 "User 6"

With GNU awk (depending on version) you may be able to edit inplace as well

  • Related