3

I do have a bash script. I want to delete a specific string from a text file. I already found a command on the online but it seems it isn't that stable..

I've tried;

mv .admins .adminsold
sed -r "s#${MYFUNCTION}(,|$)##g" <.adminsold >.admins

My input file;

# Admin rule
[[rule]]
    # Set your admin Group Ids here, ex: [ 13, 42 ]
        groupid = [  329, 2, 324, 156 ]
    # And/Or your admin Client Uids here
    useruid = []
    # By default treat requests from localhost as admin
    ip = [ "127.0.0.1", "::1" ]
    "+" = "*"

Expected file;

# Admin rule
[[rule]]
    # Set your admin Group Ids here, ex: [ 13, 42 ]
        groupid = [  329, 2, 156 ]
    # And/Or your admin Client Uids here
    useruid = []
    # By default treat requests from localhost as admin
    ip = [ "127.0.0.1", "::1" ]
    "+" = "*"
8
  • So you only need to remove 324, from the file ... right?
    – Raffa
    Aug 6 at 15:53
  • It depends on the situation. But for now, Yes
    – Erikli
    Aug 6 at 15:54
  • 1
    Please give more context. Link to your other question and explain that the thing you want to delete might be the last element. And also show us how the variable you are using is defined. You probably also want to ensure the change only happens on that specific line, right? The one that starts with groupid=
    – terdon
    Aug 6 at 16:00
  • @terdon, Yes. I want it to happen on specific line. I defined my variable like this MYFUNCTION=324
    – Erikli
    Aug 6 at 16:28
  • 1
    None are "better", they all have their pros and cons. But for this sort of thing, look into python or perl or any other high level scripting language, not low level compiled languages like the C family. It's just that the shell is very limited and really shouldn't be used for complex tasks.
    – terdon
    Aug 7 at 12:57

2 Answers 2

6

If all you need is to remove 324,(i.e. exactly: one whitespace then 324 then one comma ,) from the file, then use:

sed 's/ 324,//' file

And to edit the file itself(i.e. overwrite the original file), use:

sed -i 's/ 324,//' file

Please see this answer for more info.


Things to consider from your example:

  • ? will make the previous character optional and you nead to escape it with a backslash \ ... e.g. to make the , optional use:

    sed 's/ 324,\?//' file
    
  • If you need to match a literal /, you need to either escape it \/ or you can change the delimeter from the usual / to something else like @(or : or anything else) like so:

    sed 's@wxyz0123456789+/@@' file
    
  • If you want to apply the substitution only on lines that include groupid then specify /groupid/ as a condition before the substitution part like so:

    sed '/groupid/ s/ 324,//' file
    
8
  • 1
    You probably want a ? after the , in case the target ID is the last one listed.
    – terdon
    Aug 6 at 16:01
  • 1
    -i stands for in-place which is needed in order to find and replace "in place" so directly in the input file. You can't do in-place editing with regular piping because the file is opened in writing mode immediately (which wipes the file content)
    – Natan
    Aug 6 at 16:02
  • @terdon Nice idea ... ? would make the previous character optional ... it needs to be escaped, however, with a backslash like so sed 's/ 324,\?//' file
    – Raffa
    Aug 6 at 16:08
  • It seems working, I'm gonna check if it's stable. By the way, some code is not only numbers. Sometimes it can be base64 code too, so Is there any options which works with + and / characters?
    – Erikli
    Aug 6 at 16:13
  • 1
    ehm I would always check that the line includes groupid. But then egain.... bad practice as is. The value of groupid needs to be a variable supplied to the file and not replaced.
    – Rinzwind
    Aug 6 at 16:27
3

Since your input file appears to be TOML, you could consider using a TOML tool to manipulate it - it's likely to be more robust than using a strictly text based utility.

The tool I'm most familiar with is provided by kislyuk's yq and is a wrapper around the jq JSON tool. So for example given

$ cat .admins 
# Admin rule
[[rule]]
    # Set your admin Group Ids here, ex: [ 13, 42 ]
        groupid = [  329 , 2, 324, 156 ]
    # And/Or your admin Client Uids here
    useruid = []
    # By default treat requests from localhost as admin
    ip = [ "127.0.0.1", "::1" ]
    "+" = "*"

then to remove element 324 from the groupid array of the rules section:

$ tomlq -t --argjson id 324 '.rule[] |= del(.groupid[] | select(. == $id))' .admins 
[[rule]]
groupid = [ 329, 2, 156,]
useruid = []
ip = [ "127.0.0.1", "::1",]
"+" = "*"

Unfortunately while TOML permits comments, JSON doesn't - so they get stripped out: there are likely other TOML tools that don't have this limitation.

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.