AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 787702
Accepted
Mike
Mike
Asked: 2024-12-06 04:24:12 +0800 CST2024-12-06 04:24:12 +0800 CST 2024-12-06 04:24:12 +0800 CST

Saída de pipe para script bash

  • 772

Estou lendo o livro "sed & awk" de Dougherty e Robbins. Um dos exemplos pede para canalizar a saída para um script de shell:

sed -f nameState list | byState

Mas descobri que, para funcionar, preciso dar ao script 'byState' permissões de execução com chmod e também chamá-lo com ponto-barra:

sed -f nameState list | ./byState

Será que esse sempre será o caso? O livro é de 1997, então talvez o padrão do shell tenha mudado? Ou é porque estou usando bash e não sh ?

EDIT: Aqui está o script byState:

#! /bin/sh
awk -F, ’{
        print $4 ", " $0
        }’ $* |
sort |
awk -F, ’
$1 == LastState {
      print "\t" $2
}
$1 != LastState {
      LastState = $1
      print $1
      print "\t" $2
}’
bash
  • 2 2 respostas
  • 72 Views

2 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-12-06T15:27:43+08:002024-12-06T15:27:43+08:00

    Executar um nome de comando que não contém um /é destinado a comandos que devem ser pesquisados ​​em um dos diretórios listados em $PATH¹. Você não gostaria rm filede executar o rmcomando que por acaso está no diretório de trabalho atual em vez do rm² padrão.

    Se você quiser executar o byStateexecutável que é encontrado em um diretório específico, em oposição ao primeiro (se houver) encontrado em qualquer um dos $PATHdiretórios, você precisa invocá-lo pelo seu caminho. Como ele precisa conter pelo menos um /, para aquele que está no diretório de trabalho atual, você normalmente usa ./byStatewhich, como byStateé um caminho relativo para aquele arquivo, mas é um que contém um /. Você também pode usar /full/path/to/byStateor ././byStateou ../here/byStatewhich também funcionaria.

    Se você quiser que esse byStatescript seja executável byStatepor qualquer pessoa no sistema, independentemente do diretório de trabalho, você pode pedir ao administrador do sistema para colocar uma cópia dele em /usr/local/bin(ou qualquer diretório que esteja no padrão, $PATHembora /usr/local/binseja o local destinado aos comandos instalados localmente). Ou você pode até mesmo fazer um pacote de software para ele (como um .debarquivo se for para um sistema baseado em Debian) incluindo esse executável e sua página de manual, por exemplo, e que listaria suas dependências ( sh, awk, sortembora esses sejam softwares essenciais que sempre serão instalados e não precisam ser listados como dependências) e pedir ao administrador para instalá-lo (como com gdebi/ apt/ dpkgem sistemas baseados em Debian), e então isso poderia ser colocado em /usr/bin. Isso o tornaria mais limpo, pois seria listado como um software instalado com informações sobre seu mantenedor, onde estão os arquivos correspondentes e facilitaria a desinstalação.

    Se isso byStatefor só para você, você pode adicioná-lo a um dos seus próprios diretórios e adicionar esse diretório às suas $PATHvariáveis ​​de ambiente. Diretórios típicos para isso são ~/binou ~/.local/bin.

    Em qualquer caso, para poder executar um arquivo, obviamente você precisa ter permissão de execução nele. Para scripts, você também precisa que o arquivo tenha permissão de leitura, pois o interpretador (aqui /bin/sh) precisa ser capaz de ler o código nele para executá-lo.

    chmod a+rx byState
    

    Daria a todos ( all) read e e xecute permissão para isso. Ou você poderia especificar as permissões na íntegra com:

    chmod a=rx,u+w byState
    

    Que dá permissão de leitura+execução para todos, e também permissão de escrita para o proprietário. Ou chmod 755 byStatecom a forma octal.

    Agora, alguns problemas com seu shscript (não é um bashscript, mas bashseria capaz de interpretá-lo, se você perguntasse a ele alterando o shebang para, #! /path/to/bash -já que sua linguagem tem uma sintaxe compatível):

    Talvez seja um problema de copiar e colar, mas essas ’são aspas erradas, essas são U+2019 ASPAS ÚNICAS DIREITAS. As aspas que os shells reconhecem como operadores de aspas fortes são ', U+0027 APÓSTROPHE.

    $*unquoted no contexto de lista não faz sentido algum³. $*só faz sentido quando citado, mas isso é para juntar os parâmetros posicionais com o primeiro caractere de $IFS4, o que não é o que você quer aqui. Para passar todos os parâmetros posicionais literalmente para awk, você precisa de "$@"(que deve ser citado).

    awktem esse problema em que se você passar um nome de arquivo como foo=bar.txt, ele é tomado como uma atribuição de variável awk. Então aqui, seria melhor fazer 5 :

    cat -- "$@" | awk ...
    

    Com print $4 ", " $0, você está adicionando um espaço além do ,, então quando nessa saída você fizer, print "\t" $2, isso imprimirá uma tabulação, espaço e o campo. Provavelmente você quer que o separador de campo de entrada ( FSconforme definido por -F) e o separador de campo de saída ( OFS) sejam ambos apenas ,.

    Em $1 == LastState, cuidado, isso awkfará uma comparação numérica se os operandos parecerem números e comparação de strings 6 caso contrário. Por exemplo, ele diria que 100, 1e2e 100.0são idênticos. Se você quiser ter certeza de que uma comparação de strings será realizada, você faria $1 "" == LastState, ou ao atribuir LastState, faça LastState = $1 ""com que ele registre o fato de que é uma string e não potencialmente um número.

    Em vez de verificar a igualdade duas vezes, com LastState = $1and LastState != $1, você pode adicionar a nextno final da ação para a primeira verificação para pular a necessidade de comparar novamente, ou usar uma instrução if/ elseem uma ação executada incondicionalmente.

    sorté muito bem capaz de classificar a entrada com base no 4º campo 7 , você não precisa movê-lo para a frente.

    #! /bin/sh -
    sort -t, -k4,4 -- "$@" |
      LC_ALL=C awk -F, '
        {
          if ($4 == LastState)
            print "\t" $1
          else {
            LastState = $4
            print $4 ORS "\t" $1
          }
        }'
    

    Ou fatorando print "\t" $1e tornando-o mais legível/direto:

    #! /bin/sh -
    sort -t, -k4,4 -- "$@" |
      LC_ALL=C awk -F, '
        $4 != LastState {print LastState = $4}
        {print "\t" $1}'
    

    ¹ Para aqueles que não são um comando ou função interna do shell ou alias (quando literal e sem aspas) de uma das palavras-chave na sintaxe do shell, como while, for... (também quando literal e sem aspas).

    ² Décadas atrás, não era incomum incluir .ou a string vazia, ambas significando o diretório de trabalho atual em $PATH, mesmo na frente (!), onde você encontraria esse tipo de problema, mas ninguém seria tolo o suficiente para fazer isso hoje em dia.

    ³ Basicamente, isso é pedir ao shell para juntar os parâmetros posicionais (os argumentos para o script) com o primeiro caractere de $IFS4 e então (por causa das aspas faltantes), dividir o resultado novamente em qualquer caractere de $IFSe sujeitar cada palavra resultante a globbing, também conhecido como geração de nome de arquivo, também conhecido como expansão de nome de caminho . Isso $*faria sentido no rcshell, o sucessor do Bourne shell, embora isso infelizmente nunca tenha acontecido, mas você precisaria de um #! /bin/rcshebang, ou zshwhere $*expande para os parâmetros posicionais não vazios quando não estiver sendo executado na emulação sh/ .ksh

    4 Com o Bourne shell, um shell pré-POSIX que ainda era encontrado /bin/shem alguns sistemas em 1997, que os uniria com espaço, independentemente do valor de $IFS.

    5 cat não tem esses problemas, mas (e isso também se aplica a sorte awk) trata -como entrada padrão, então se você tiver um arquivo chamado -, você tem que passá-lo como ./ou qualquer outro caminho para ele para contornar isso.

    6 Com muitas awkimplementações, isso nem é uma comparação de string byte a byte, mas se as duas strings são classificadas da mesma forma. Executar awkno locale C garantiria que isso fosse uma comparação de string.

    7 A -k start,end[flag]sintaxe é a nova (como no início dos anos 90, talvez no final dos anos 80), é possível que em 1997 ainda houvesse sortimplementações que não a suportavam e apenas a sintaxe antiga, agora obsoleta +offset, o que pode explicar por que não a usavam.

    • 5
  2. Marc Wilson
    2024-12-06T04:56:43+08:002024-12-06T04:56:43+08:00

    Sim. Se você vai chamar o script assim, ele precisa ser marcado como executável (e, de preferência, ter um shbang). Isso não é novidade.

    Seu termo "ponto-barra" está simplesmente especificando o caminho para o script, o único ponto representando o diretório atual. Como apontado por @ilkachu, é um problema de segurança incluir "ponto" no seu caminho, isso levaria a qualquer diretório que possa estar $CWDno momento aparecendo no seu caminho de pesquisa.

    • 0

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve