删除匹配字符串中的第 n 行(仅在文件中出现一次)

删除匹配字符串中的第 n 行(仅在文件中出现一次)

我有一个与删除出现在n+2匹配字符串之后位置的字符串相关的问题,该匹配字符串位于n用于awk多个文件的位置。我可以使用以下命令打印它:

 awk -F '/radius-server/{nr[NR+4]}; NR in nr' *

其中匹配的字符串是radius-server.由于我不太熟悉, awk如果有人可以帮助我,我将不胜感激就地删除这一行,这意味着我希望在删除完成后修改并保存文件。下面是一个示例场景 - file 1未经修改

 radius-server dz7HQQH4EqT5 1645-1646
 !
 oj5icqh1dGpSK
 !  
 alias exec t telnet
 alias exec sis show interface status
 !

file 2,修改后为——

radius-server dz7HQQH4EqT5 1645-1646
!
!
alias exec t telnet
alias exec sis show interface status
!

我知道我可以使用模式匹配方法sed -i '/pattern/d'来删除它,但这不是我想要的,因为值会随着文件的不同而变化。任何帮助将非常感激。

答案1

sed 似乎是正确的工具:

sed -i '/radius-server/!b;n;n;d' filename

怎么运行的:

/radius-server/!b # as long as it's NOT 'radius-server' do nothing (branch to end)
n # read next line (replace current line with next line)
n # same as above - we now read 2 lines
d # delete the current line

更新 - 要修改多个文件,只需使用 glob 而不是文件名,例如

sed -i '/radius-server/!b;n;n;d' *

答案2

除非你有 GNU awk 4.1.0 或更高版本...

您不会有像 sed-i选项这样的选项,因此可以这样做:

对于 * 中的文件
awk -v 行=2 'BEGIN { 忽略 = -1 } /radius-server/ { 忽略 = NR + 行 } NR != 忽略 { print }' "$file"
完成 > 结果.txt

其工作原理如下:

BEGIN { ignore = -1 }             # initialize ignore with -1 so NR will never
                                  # be equal to it by accident

/radius-server/ { ignore = NR + lines } # when the radius-server is found, set ignore to the
                                  # line we want to ignore

NR != ignore { print }            # unless the current line is that line, print
                                  # it.

注意:这-i并不神奇,它还会创建一个临时文件,sed只是为您处理它。

更新

如果需要递归到子目录:

寻找 。 -type f -exec awk ... {} ; > 结果.txt

在这两种情况下,您可能应该将 result.txt 放在不同的目录中。否则,它将被匹配并用作输入文件。

答案3

PATH_TO_FOLDER="/some/path/to/folder/"
FILE_EXTENSION=".ext"
FILES=$(ls ${PATH_TO_FOLDER}/*${FILE_EXTENSION})

for FILE in $FILES; do
FILENAME=$(basename $FILE ${FILE_EXTENSION})
TMP_FILE=${PATH_TO_FOLDER}/${FILENAME}.tmp
awk -v Lines=2 '{if($0~"radius-server"){ 
print;
for(i=0;i<=Lines;i++)
{
getline;
if(i==Lines){
next;
}else{
print; 
}
} 
}
else{
print;
}
}' $FILE > $TMP_FILE
mv ${TMP_FILE} ${FILE}

原则上这应该可行。基本上,如果该行包含 radius-server 将打印该行,然后它将迭代接下来的 3 行 0 将打印第一行 1 将打印第二行,然后 3 将完全跳过第三行。对于所有其他情况,这些行将按原样打印。

相关内容