O arquivo ( myfile.txt
) contém os seguintes dados:
abc#ab1=23
nrt#
#clb1aX
amd#322
Saída desejada:
abc
nrt
clb1ax
amd
eu poderia fazer assim,
for i in `cat myfile.txt`
do
s1=`echo $i | cut -d'#' -f1`;
s2=`echo $i | cut -d'#' -f2`;
if [ "$s1" == "" ]; then
echo "$s2"
else
echo "$s1"
fi;
done;
Mas existe alguma maneira de fazer isso sem usar for
e if
, como usar awk
ou sed
ou cut
ou outra coisa em uma única linha?
Solução curta
awk
:A saída:
Responda
Ele pode ser unido em uma linha adicionando o
;
após o}
, mas será mais difícil lê-lo assim.Explicação
sed -i
Mantenha as alterações no arquivo, não as grave emstdout
./^#/
- Whensed
está posicionado na linha que começa com#
.s/#\(.*\)/\1/
- Substitua a primeira ocorrência de#[everything]
por[everything]
.b
- Pare o trabalho na linha atual e comece a trabalhar na próxima.(Evita
s/#.*//
que o comando seja executado.)s/#.*//
- Remova a primeira ocorrência de#[everything]
.(Isso funcionará para todas as linhas, a menos que o
b
comando anterior tenha saído antes.)myfile.txt
Arquivo no qualsed
irá executar.E se você não tivesse campos com valor ou não fosse apenas na segunda coluna? então você precisaria.
Exemplo dado abaixo:
dará saída:
Ou usando
sed
ecut
:s/^#\+//
remove os hashes principais#
(ocorreram uma ou mais vezes)/^$/d
remove linha vazia produzida após acima, onde uma linha era toda hashes#####
ou remove linhas vazias no arquivo, se houver.cut -d'#' -f1
impressão do primeiro campo-f1
quando os arquivos são delimitados por um hash-d'#'
Ou
sed
apenas:s/^\([^#]*\)#.*/\1/
captura um grupo de início de correspondência desde o início da linha para qualquer coisa até um primeiro hash visto e apenas o imprime no resultado e ignora o resto.Usando
perl
- assumindo apenas um único#
na entrada, conforme fornecido na amostra[^#]\K#.*
para excluir todos os caracteres da primeira ocorrência de#
se houver um não#
caractere precedendo-o|^#
caso contrário, remova#
do início da linhaA mesma coisa com
sed
outro sed
Se você deseja remover linhas apenas com ####