br sed: Excluindo uma lista de caminhos de um conjunto de arquivos

0

Eu tenho um arquivo chamado common.txt que contém uma lista de caminhos absolutos. Por exemplo:

/etc
/etc/group
/var/log/syslog

Eu também tenho um conjunto de arquivos < hostname > .txt que também contém uma lista de caminhos absolutos. Aqui está um exemplo (chame de host1.txt ):

/root/.bashrc
/var/log/syslog
/etc/hosts
/bin/true
/etc
/sbin/rtmon
/etc/group

Eu gostaria de remover todos os caminhos que aparecem em common.txt de todos os arquivos no conjunto de arquivos < filename > .txt . Assim, o arquivo de exemplo host1.txt acima se tornaria:

/root/.bashrc
/etc/hosts
/bin/true
/sbin/rtmon

Eu escrevi o seguinte script Bash para fazer isso:

#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
   done
done < common.txt

Estou tendo dificuldade em obter o comando sed correto. O que é mostrado acima resulta em todos os arquivos operados após ficarem vazios.

Como posso corrigir isso para atingir minha meta?

    
por Dave 08.03.2018 / 17:57

3 respostas

1
#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

declare -r SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
declare -r FILES_DIR=${SCRIPT_DIR%/*}

while read -r ONE_PATH
do
   for ONE_FILE in $(find "$FILES_DIR" -maxdepth 1 -type f -print)
   do
      if [[ "$ONE_FILE" == *".swp" ]] ||
         [[ "$ONE_FILE" == *"common.txt" ]]; then
         continue
      fi

      sed -i '\|^'"$ONE_PATH"'$|d' "$ONE_FILE"
   done

echo "Done removing $ONE_PATH"
done < "$SCRIPT_DIR"/../common.txt

exit 0
    
por 09.03.2018 / 16:19
0

Posso sugerir uma solução que não use sed?

sort common.txt > common.txt.sorted
for f in host1.txt host2.txt host3.txt ; do
    sort $f > $f.sorted
    diff common.txt.sorted $f.sorted | egrep '^>' | sed -e 's/^> //' > $f.output
    rm $f.sorted
done

sort classifica as listas em ordem alfabética. diff encontra as diferenças entre o arquivo e common.txt . O egrep seleciona linhas que começam com > , que são linhas em host1.txt.sorted , mas não em common.txt.sorted . Finalmente, sed remove o primeiro > (que é > seguido por um espaço) adicionado por diff .

A lista de saída também estará em ordem alfabética.

    
por 12.03.2018 / 08:20
-1

Primeiro, a entrada deve ser ordenada ao contrário. Não adianta remover / etc e depois procurar por / etc / group. Em seguida, verificamos se o arquivo pode ser gravado (se não for pular). Então ONE_PATH deve ser escapado e, em seguida, sed pode fazer o seu trabalho,

sort -r common.txt \
| while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      if [ -w "$ONE_FILE" ]
      then
        # sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
        ONE_PATH_ESC=$(echo "$ONE_PATH" | sed "s!/!\\/!g")
        sed -i 's/^'"$ONE_PATH_ESC"'//' "$ONE_FILE"
      fi
   done
done

Com os dados de teste fornecidos, você recebe:

$ pr -n host1.txt
1   /root/.bashrc
2
3   /hosts
4   /bin/true
5
6   /sbin/rtmon
7

Existem 3 linhas vazias.

    
por 08.03.2018 / 21:15