What I have
I over-documented my meta statements in my scripts. There are many. They all start with something like this:
#!/bin/bash
# Title and other notes information
## I may have other lines here, or not
ruler=( monarch ) # Type of leader
kingdom=( "Island" ) # Type of territory
zipcode=( 90210 ) # Standard, 3-12 digits, hyphens allowed
datatype=( 0-9- ) # Datatype
favoritepie=( "Cherry" ) # A happy memory
aoptions=( "Home address" "Work address" "Mobile" ) # List custom options
boptions=( ) # List secondary options
aopttypes=( string string phonenum ) # Corresponding datatypes for options
bopttypes=( ) # Corresponding datatypes for secondary options
sourced=( ) # Sourced text in this script, such as settings
subscripts=( installusr ) # Valid BASH scripts that this script may call
...
# Script continues
...I need it to become this...
#!/bin/bash
# Title and other notes information
## I may have other lines here, or not
ruler=( monarch )
kingdom=( "Island" )
zipcode=( 90210 )
datatype=( 0-9- )
favoritepie=( "Cherry" )
aoptions=( "Home address" "Work address" "Mobile" )
boptions=( )
aopttypes=( string string phonenum )
bopttypes=( )
sourced=( )
subscripts=( installusr )
...
# Script continues
- There are only 11 lines like this and they are first like this. Any such comments later in the scripts must be left alone.
- There might be comments before these lines, but the number of lines before the 11 arrays varies from script to script.
- Every comment starts after the consistent pattern
) #
...
What I need
I need to remove the comments after these array statements.
What I have
I can run this...
sed 's/ ) # .*/ )/' *
But, I want to limit that to only the first 11 occurrences per file.
From this answer I get a pattern to match the first single match, giving me this...
sed '0,/ ) # .*/s// )/' *
...but that only works for the first occurrence.
I could put it into a loop:
#!/bin/bash
counter=1
while [ "$counter" -le "11" ]; do
sed '0,/ ) # .*/s// )/' *
counter=$(expr $counter 1)
done
Is that 'proper'?
This loop makes the assumption that all files will match evenly, running blankly for all files. If possible, I'd like the loop to run for each file, not for all files based on a counter. But, I'm not sure how to do that.
Is that the best way to do this? Or, is there a more "proper", fail-safe way using other Linux tools?
CodePudding user response:
If I'm understanding your requirements correctly, following will work:
#!/bin/bash
for file in *; do
temp=$(mktemp tmp.XXXXXX)
awk '
/\)[[:space:]]*#/ && c < 11 {sub(/[[:space:]]*#.*/, "")}
1
' "$file" > "$temp"
mv -f -- "$file" "$file".O # backup file
mv -f -- "$temp" "$file"
done
If GNU awk
is available, -i inplace
option will work to overwrite the file instead of creating a temp file.
CodePudding user response:
Would be a bit easier with awk:
[Bash-5.2] % cat file
# this is a comment
a1=( a1 ) # a1
a2=( a2 ) # a2
a3=( a3 ) # a3
a4=( a4 ) # a4
a5=( a5 ) # a5
[Bash-5.2] % awk 'n < 3 && / [)] # / { sub(" [)] # .*", " )"); n } { print }' file
# this is a comment
a1=( a1 )
a2=( a2 )
a3=( a3 )
a4=( a4 ) # a4
a5=( a5 ) # a5