删除BASH内联注释,但仅在数组和前11个出现之后



我有什么

我在脚本中过多地记录了我的元语句。有很多。它们都是这样开头的:

#!/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
outsidethewire=( "key 971" ) # Leave this comment here
somearray=( "sliced apples" "pie dough" ) # Mother's secret recipe

…我要把它变成这样……

#!/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
outsidethewire=( "key 971" ) # Leave this comment here
somearray=( "sliced apples" "pie dough" ) # Mother's secret recipe
  • 只有11行这样的,它们是这样的。
  • 这些行之前可能会有注释,但是11个数组之前的行数因脚本而异。
  • 每条评论都以一致的模式) #
  • 开始

我需要的

我需要删除这些数组语句后面的注释。

我有什么

我可以运行这个…

sed 's/ ) # .*/ )/' *

但是,我想将其限制为每个文件只出现前11次。

从这个答案我得到一个模式匹配第一个单一的匹配,给我这个…

sed '0,/ ) # .*/s// )/' *

…但这只适用于第一次出现。

我可以把它放入一个循环:

#!/bin/bash
counter=1
while [ "$counter" -le "11" ]; do
sed '0,/ ) # .*/s// )/' *
counter=$(expr $counter + 1)
done

这样"合适"吗?

此循环假设所有文件将均匀匹配,对所有文件都空白运行。如果可能的话,我希望循环对每个文件运行,而不是基于计数器对所有文件运行。但是,我不知道该怎么做。

这是最好的方法吗?或者,是否有一种使用其他Linux工具的更"合适"、更安全的方法?

如果我理解正确的话,您想要匹配右括号)之后的注释,并删除文件中的前11个注释,而不管右括号之后是否出现类似的匹配。

假设文件的内容是;

$ cat input_file
#!/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
# 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

使用sed,然后匹配感兴趣的行,对符合条件的前11行执行操作。

$ sed '/) #/{1,+10s/#.*//}' input_file
#!/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 )
# 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

如果我正确理解了您的要求,下面将工作:

#!/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

如果GNU awk可用,-i inplace选项将覆盖文件,而不是创建临时文件:

#!/bin/bash
for file in *; do
gawk -i inplace -v inplace::suffix=.O '
/)[[:space:]]*#/ && c++ < 11 {sub(/[[:space:]]*#.*/, "")}
1
' "$file"
done

或简单的:

#!/bin/bash
gawk -i inplace -v inplace::suffix=.O '
/)[[:space:]]*#/ && c++ < 11 {sub(/[[:space:]]*#.*/, "")}
1
' *

这可能适合您(GNU sed):

sed -E 'x;/x{11}/{x;b};x;/) #.*/{s//)/;x;s/^/x/;x}' file

本质上,在保持空间中保留一个计数器,如果所需类型的11条注释已被删除,则不需要进一步处理一行。

检查等待空间计数器,如果是11,就跳伞。

否则,如果该行符合所需的条件,则删除注释并增加保持空间中的计数器。

在所有其他情况下,不进行任何处理。

最新更新