-1

I have a file which has several lines.

I wish to update the file while making sure that the last visible character of each line of the file is a single quote '. In case not, then we should add the single quote at the end of each line.

If the single quote is the last character in a line then leave it as is.

cat test.txt

fahsjhjkhkjhjhajkhjf
afasfsfsfffsfasf'
aaffa' sfff
wfafsfsaffs'
fsafsfs'afffafsasf

Expected output:

fahsjhjkhkjhjhajkhjf'
afasfsfsfffsfasf'
aaffa' sfff'
wfafsfsaffs'
fsafsfs'afffafsasf'
Ashar
  • 491
  • 2
    You were just shown how to do this on the last line of a file: sed "\$s/[^']\$/&'/" file. To do it on any line, just remove the \$ address condition. – steeldriver Mar 27 '22 at 18:26
  • @steeldriver i tried tac test.txt | sed '1,/[[:graph:]]/ { /[[:graph:]]/!d; }' | tac | sed "\$s/[^']/&'/" and it does not work on the sample i provided. – Ashar Mar 27 '22 at 18:39
  • i also tried tac test.txt | sed '1,/[[:graph:]]/ { /[[:graph:]]/!d; }' | tac | sed "\$s//'/" but i get error sed: -e expression #1, char 0: no previous regular expression – Ashar Mar 27 '22 at 18:42
  • 4
    Why would you want to use tac? Don't treat programming as a "cargo cult" but instead take some time to try and understand the solutions you're given. It makes things so much easier... – Chris Davies Mar 27 '22 at 20:46
  • If you can have empty input lines that you want changes to a single ' then include that case in your example as some potential solutions would fail given that input. What should the output be if an input line ends with 2 's, e.g. would input of foo'' output foo'' or foo'? – Ed Morton Mar 28 '22 at 00:27

5 Answers5

2

If matching the single quote whether it is there or not, and if present, replacing it is acceptable, then you can try this sed.

$ sed "s/\([^']*\)'\?$/\1'/" input_file
'fahsjhjkhkjhjhajkhjf'
afasfsfsfffsfasf'
aaffa' sfff'
wfafsfsaffs'
fsafsfs'afffafsasf'

This uses back referencing to capture every character up to the end of the line. If a single quote is found at the end of the line, then it is excluded/removed by placing the single quote outside of the capturing parenthesis.

Everything captured within the parenthesis is then returned with \1 with the single quote hardcoded to the end of each line.

sseLtaH
  • 2,786
  • 1
    Interesting approach. You should say more about how/why this works, and why you chose it over they’s shorter (and, arguably, more obvious) answer. … … … … … … … … … … … … … … … Please do not respond in comments; [edit] your answer to make it clearer and more complete. – G-Man Says 'Reinstate Monica' Mar 29 '22 at 04:30
2

The sed expression s/[^']$/&'/ inserts a single quote at the end of any line that ends with a character that is not a single quote.

In the shell:

sed "s/[^']$/&'/" file

Since the expression contains a single quote, I'm choosing to write the expression in double quotes instead. To make an in-place edit, use sed with its -i option if it implements this nonstandard option at all.

To also insert a single quote on empty lines, you could use an extra expression targeting empty lines specifically, or you could always insert a single quote at the end of the line and then replace any double single quotes that this results in.

I.e., either

sed -e "s/[^']$/&'/" -e "/^$/s//'/" file

or

sed -e "s/$/'/" -e "s/''$/'/" file
Kusalananda
  • 333,661
1

something like can do the work:

awk -v a=\' '{print $0 a}'  input.file

If you want to avoid double quotes on the end you can try something like:

 awk -v a=\' '{print $0 a}'  input.file|sed "s/''$/'/"
Romeo Ninov
  • 17,484
1

Please use sed as it is supposed to.

To add a ' at the end of all lines you do

sed "s/$/'/" file

To do an operation on some lines only, you use an address. The address of lines ending with ' is /'$/. You invert the address seletion by a !, so you get

sed "/'$/!s/$/'/" file

Short, functional, portable and also covering the empty-line-case.

(Beware not to have stupid history expansion active: set +H)

Philippos
  • 13,453
0

Assuming you want empty input lines to become ' in the output and input like foo'' to be output as foo':

$ sed "s/'*$/'/" file
fahsjhjkhkjhjhajkhjf'
afasfsfsfffsfasf'
aaffa' sfff'
wfafsfsaffs'
fsafsfs'afffafsasf'
Ed Morton
  • 31,617