5

I have a text file called sample.text which looks like this

Continent Lat/Lon: 46.07305 / -100.546
Country Lat/Lon: 38 / -98
City Lat/Lon:(37.3845) / (-122.0881)

I want to process this text to get output as follow without using temporary file

Continent Lat/Lon: 46.07305 / -100.546
Country Lat/Lon: 38 / -98
City Latitude: (37.3845) 
City Longitude: (-122.0881)

I don't have control over the values of latitude/longitude.

I have accomplished this using 2 awk scripts

BEGIN { FS=":"}  {print $2} | BEGIN { FS="/"}  {printf "City Latitude:%s\nCity Longitude:%s\n",$1,$2} 

As I want to write the original file, is there any way to do it using

sed -i  

All inputs are appreciated.

3
  • 1
    You mean like: 's/City.*\(([^)]*)\) \/ \(.*\)/City Latitude: \1\nCity Longitude: \2/' ?
    – Runium
    Mar 25 '16 at 5:15
  • 1
    @Sukminder. Yes it works perfectly. Can you explain what you did there? Mar 25 '16 at 5:25
  • You need to learn regex (regular expression) learn step by step to be able to understand Mar 25 '16 at 5:36
2
sed -i 's,^City Lat/Lon:(\(.*\)) / (\(.*\))$,City Latitude: (\1)\nCity Longitude: (\2),' /path/to/file

Explanation

  • sed -i 's,foo,bar,' /path/to/file: do sed inplace, replacing foo with bar. N.B. I use , as delimiters here instead of /, so that I can use / in the string without having to escape them.
  • ^City Lat/Lon:(\(.*\)) / (\(.*\))$: find any occurrence of this regex, where ^ and $ are the beginning and end of the line respectively, and each of the two \(.*\) represents a capturing group.
  • City Latitude: (\1)\nCity Longitude: (\2): replace with this string, where \1 and \2 represent the groups captured from the first expression, and \n is a newline.
6
  • What do you mean by '\1 and \2 represents the groups captured from first expression' ? Can you please explain for me that how these values are gettng generated .
    – Pacifist
    Mar 25 '16 at 7:12
  • @VineetSharma The second dot point will twice capture different strings .* with the escaped parens \(...\). That is, the strings .* are matched as normal, and these strings are "captured", to be used later. In this case, they represent the latitude and longitude. Then, in the third dot point, we can re-use these previously captured strings, which will replace the placeholders \1 and \2, which represent the first and second captured group respectively.
    – Sparhawk
    Mar 25 '16 at 7:38
  • 1
    sed actually uses temp files. I am trying to deal with permissions issue about it. Jul 3 '20 at 5:57
  • 1
    @SalathielGenèse This answer was to a very specific question that requested the use of sed -i. You may want to ask a new question for your problem.
    – Sparhawk
    Jul 3 '20 at 8:02
  • @Sparhawk Google lead me here, too, with the title of the question being "(...)replace a string in a file without using temp file with SED" but as sed creates a temp file this answer failing to solve that big question in the headline. Jan 15 at 14:46
0

With sed -i having a truly in place editing is not possible as under the hood it actually is crating a temporary file for you anyway. However you can store the result for yourself somewhere and then write that to the file. A simple way is to use bash variables for that.

Just make sure your file is not to big. Should be fine for most files, but if you have a 69 GB log file, maybe write it to /tmp/ instead.


Change

sed -i '<some regex>' --any-flags-you-want /some/file

to

SED_RESULT=$(sed '<some regex>' --any-flags-you-want) && echo ${SED_RESULT} > /some/file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.