Executar um bloco condicionalmente na saída do grep

0

Encontrei várias soluções para esse problema, mas infelizmente nenhuma delas parece funcionar na minha caixa do Windows.

Estou executando um loop FOR em um arquivo em lotes para percorrer vários arquivos de texto. Para cada arquivo de texto, desejo ECHO seu nome (e possivelmente redirecionar a saída para o arquivo) se um grep (de WinGNU) retornar uma linha. Uma rápida pesquisa no google me mostra como fazer isso:

IF grep -c pattern file ( stuff )

No entanto, isso gera um erro

-c was unexpected at this time.

Como alternativa, imaginei que poderia usar o código de saída de grep --quiet da seguinte forma:

grep -q pattern file
IF ERRORLEVEL 1 ( stuff )

Isso sempre falha no teste IF, mesmo quando o grep é bem-sucedido.

Existe uma boa maneira de executar uma instrução condicional no Windows se o meu grep encontrar uma correspondência?

Meu código é:

SET locations=( a, long, list, of, last, two, octets )
SETLOCAL ENABLEDELAYEDEXPANSION

FOR %%r IN %locations% DO (
    grep -i "^\[CardSwipe\]" \10.0.%%r\path\to\file.ini
    IF ERRORLEVEL 1 echo %%r

Minha saída é:

[this line left intentionally blank] :)
    
por Adam Smith 31.07.2014 / 01:01

1 resposta

1

Não consigo pensar em uma boa maneira de fazer isso com o Batch, especialmente porque você está trazendo ferramentas de linha de comando não nativas com as quais não estou familiarizado. No entanto, o PowerShell geralmente é muito mais adequado para tarefas como essa.

Isso deve fazer o trabalho para você no PowerShell:

$Hosts = @('1.1','1.2','101.243','54.28')
$Hosts | ForEach-Object {
    if ((Get-Content "\10.0.$_\path\to\file.ini" | Select-String "^\[CardSwipe\]").length -ne 0) {
        Write-Output $_}}

Aqui está o detalhamento:

  1. Definimos $Hosts como uma matriz contendo strings que representam os dois últimos octetos de cada sistema a ser verificado. Um método alternativo de configuração seria ter um arquivo de texto com uma entrada por linha.
  2. Em seguida, enviamos a matriz para ForEach-Object , o que, como o nome indica, executará comandos para cada objeto na matriz. Se você usar um arquivo de texto como sua lista, precisará buscá-lo com Get-Content e enviá-lo para ForEach-Object no lugar da variável.
  3. O script na condição if é o que você vai fazer para você.
  4. Get-Content faz o que diz na lata - obtém o conteúdo das coisas.
  5. "\10.0.$_\path\to\file.ini" é o alvo que estamos dando a Get-Content . Envolvendo a string entre aspas duplas, estamos dizendo ao PowerShell que queremos que ele expanda variáveis dentro da string antes de passar o parâmetro. $_ é uma variável interna que faz referência ao objeto atual sendo trabalhado por coisas como ForEach-Object .
  6. A saída de Get-Content é canalizada para Select-String . Select-String é mais ou menos grep para o PowerShell - na verdade, estou um pouco surpreso por não haver um alias interno para este, pois outros cmdlets (que chamam de comandos do PowerShell) têm aliases para comandos * nix semelhantes, como ls e wget.
  7. "^\[CardSwipe\]" - Ah sim. Select-String leva o RegEx pelo caminho.
  8. A quebra de comandos entre parênteses permite que você recupere diretamente as propriedades dos objetos que elas geram, sem precisar primeiro descarregá-las para variáveis ou qualquer outra coisa. Então, ( ... ).length significa que eu quero que o comprimento de qualquer objeto seja gerado pelo script dentro dos parênteses. Para strings, esse é o tamanho básico do caractere. Para matrizes, esse é o número de membros na matriz. Quando um arquivo de texto ou objeto semelhante é recuperado, ele é retornado como "array de strings". Assim, o valor da propriedade length do objeto será igual ao número de linhas no texto.
  9. -ne é o operador de comparação para "diferente de". Se Select-String não encontrar nenhuma correspondência, sua saída será uma matriz nula com comprimento zero. Qualquer outra coisa terá comprimento 1 ou mais, então acionamos o if on -ne 0 .
  10. Write-Output é outro desses comandos autoexplicativos. Escreve saída. Nesse caso, estamos informando que queremos exibir o objeto atual sendo processado por ForEach-Object . Naturalmente, como isso está dentro do bloco if , isso só acontecerá quando o arquivo ini corresponder às condições dadas. A saída será qualquer um dos "dois últimos octetos" sendo processados quando isso aconteceu.
por 31.07.2014 / 03:06