批处理文件 - 主机文件编辑器 - 防止重复条目 - 删除以前添加的条目

Batch File - Hosts file editor - prevent duplicate entries - delete previously added entries

好的,这就是我到目前为止所得到的。 这是为了在主机文件中添加要阻止的网站,并允许用户在需要时删除条目。当尝试添加要阻止的网站时,有时它会创建一个新行,然后将条目放在它之前的行中。这不是我想要的。我希望它创建一个新行,然后在该行上添加条目。由于某种原因,它有时会起作用,而有时则根本不起作用。我收到一条错误消息,指出查找参数不正确。我正在使用 Find 命令查看条目是否已在主机文件中。如果是,我希望它避免添加它。如果不是,那么我想添加它。当我尝试删除一个条目时,批处理崩溃了,所以我不太确定我在这里做错了什么。我试图找到条目并将其替换为任何内容。我真正想做的是删除整行,这样我就不会得到很多空行。 任何帮助是极大的赞赏。谢谢!

@echo off
TITLE Modifying your HOSTS file
COLOR F0

:LOOP
cls
SET "CHOICE="
ECHO Choose 1 to block a website 
ECHO Choose 2 remove a blocked website 
ECHO Choose 3 to exit
SET /P CHOICE= selection %CHOICE%
GOTO %CHOICE%

:1
cls
SET /P WEBSITE=Enter the name of the website to add:
SET HOME=     127.0.0.1 
SET NEWLINE=^& echo.
SET BLOCKEDSITE=%HOME% %WEBSITE%

FIND /C /I %BLOCKEDSITE% %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 ECHO %NEWLINE%^%BLOCKEDSITE%>>%WINDIR%\System32\drivers\etc\hosts
ECHO Website blocked
ping 127.0.0.1 -n 5 > nul
GOTO LOOP

:2
cls
SET /P WEBSITE=Enter the name of the website to remove:

SETLOCAL ENABLEEXTENTIONS DISABLEDELAYEDEXPANSION

SET "HOME=     127.0.0.1 "
SET "BLOCKEDSITE=%HOME% %WEBSITE%"
SET "REPLACE="
SET "HOSTSFILE=%WINDIR%\system32\drivers\etc\hosts"

FOR /F "DELIMS=" %%i IN ('TYPE "%HOSTSFILE%" ^& BREAK ^> "%HOSTSFILE%" ') 
DO 
(
    SET "LINE=%%i"
    SETLOCAL ENABLEDELAYEDEXPANSION
    >>"%HOSTSFILE%" echo(!LINE:%BLOCKEDSITE%=%REPLACE%!
    ENDLOCAL
)

ECHO Website unblocked

GOTO LOOP

:3
EXIT

请注意,术语 website 在引用 hosts 文件的条目时具有误导性。 hosts 文件的条目用于 DNS 主机名到 IP 地址的自定义映射,文件中存在的任何主机名不一定托管网站。使用术语 website 可能会导致错误的印象,即可以将类似 http://www.example.com 的内容添加到主机文件中,这是不正确的。

如果主机已存在于主机文件中,则跳过该主机:
使用 find 的问题是 %BLOCKEDSITE% 有嵌入的空格,所以你应该把它括起来并使用:

FIND /C /I "%BLOCKEDSITE%" %WINDIR%\system32\drivers\etc\hosts

但它还有另一个问题:由于它依赖于 %BLOCKEDSITE% 规定的 IP 地址和主机名之间的确切间距,它仅适用于批处理文件添加的条目。此外,用户可能通过在包含该条目的行的开头放置 # 来注释掉(禁用)条目,即使条目被禁用,您的批处理代码也会跳过添加主机。

这可以通过使用 findstr 及其正则表达式语法来解决。例如:

findstr /IRC:"^ *127\.0\.0\.1 *example\.com *$" "%WINDIR%\system32\drivers\etc\hosts"

正在从主机文件中删除条目:
FOR 循环中,您只需跳过写入包含指定条目的行:

if "!Line!"=="!LINE:%BLOCKEDSITE%=!" echo(!Line!>>"%HOSTSFILE%"

但它又不准确,并且遇到了前面提到的跳过添加条目的相同问题。再次使用 findstr 您可以轻松删除包含不需要的条目的行:

findstr /VIRC:"^ *127\.0\.0\.1 *example\.com *$" "%HOSTSFILE%" > "%HOSTSFILE%.tmp"
del "%HOSTSFILE%"
ren "%HOSTSFILE%.tmp" "hosts"

根据上述几点,脚本可以重写为:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
title Modifying your HOSTS file
color F0

set "HOSTSFILE=%WINDIR%\system32\drivers\etc\hosts"
set "HOME=127.0.0.1"
set "PROMPT_TEXT=Enter the host name to"
set "ACTION_TEXT[1]=add"
set "ACTION_TEXT[2]=remove"
set "FindEmptyLine=^ *$"
set "NewLineAppended="
cls
setlocal EnableDelayedExpansion
:LOOP
echo,
echo 1. Block a host
echo 2. Remove a blocked host
echo 3. Exit
choice /C "123" /N /M "Choose an item [1, 2, 3]: "
set "Item=%errorlevel%"

goto choice%Item%

:choice0 // User Pressed CTRL-C
:choice3
exit /b

:choice1
call :Common
set "HostEntry=!HOME! !HOST!"
findstr /IRC:"!FindEntry!" "!HOSTSFILE!"> nul && (
    echo The host !HOST! is already blocked, No action taken.
) || (
    if not defined NewLineAppended (
        REM This will append a new line ONLY if the file does not end by LF character
        type "!HOSTSFILE!" | findstr $ > "!HOSTSFILE!.tmp" && (
            del "!HOSTSFILE!"
            ren "!HOSTSFILE!.tmp" "hosts"
            set "NewLineAppended=1"
        )
    )
    echo !HostEntry!>>"!HOSTSFILE!"
    echo The host !HOST! blocked
)
goto LOOP

:choice2
call :Common
findstr /VIR /C:"!FindEntry!" /C:"!FindEmptyLine!" "!HOSTSFILE!">"!HOSTSFILE!.tmp" && (
    del "!HOSTSFILE!"
    ren "!HOSTSFILE!.tmp" "hosts"
    echo The host !HOST! unblocked
)
goto LOOP

:Common
set "HOST="
set /P "HOST=!PROMPT_TEXT! !ACTION_TEXT[%Item%]! (e.g. example.com): "
if not defined HOST (
    (goto)2>nul
    goto LOOP
)
set "FindEntry=^^ *!HOME! *!HOST! *$"
set "FindEntry=!FindEntry:.=\.!"
exit /b