Solução awk
curta:
awk -F'#' 'NF{ print ($1 != "" ? $1 : $2) }' file
A saída:
abc
nrt
clb1aX
amd
O arquivo ( myfile.txt
) contém dados da seguinte forma:
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 há alguma maneira de fazer isso sem usar for
e if
, como usar awk
ou sed
ou cut
ou algo mais em uma única linha?
sed -i "/^#/ { s/#\(.*\)//; b }
s/#.*//" myfile.txt
Ele pode ser unido em uma linha adicionando o ;
após o }
, mas será mais difícil lê-lo assim.
sed -i
Mantenha as alterações no arquivo, não as grave em stdout
.
/^#/
- Quando sed
está posicionado na linha que começa com #
.
s/#\(.*\)//
- Substitua a primeira ocorrência de #[everything]
por [everything]
.
b
- Interrompa o trabalho na linha atual e comece a trabalhar no próximo.
(Impede que o comando s/#.*//
seja executado).
s/#.*//
- Remove a primeira ocorrência de #[everything]
.
(Isso funcionará para todas as linhas, a menos que o comando anterior b
tenha saído antes.)
myfile.txt
Arquivo no qual sed
será executado.
E se você não tivesse campos com valor ou não fosse apenas na segunda coluna? então você precisaria.
awk -F'#' '{for(i=1; i<=NF; i++) if ($i != "") {print $i; break} }' infile
Dada abaixo da amostra:
abc#asd=123 nrt# #clsdX #### ###here acn#123
fornecerá a saída:
abc
nrt
clsdX
here
acn
Ou usando sed
e cut
:
cut -d'#' -f1 <(sed 's/^#\+//; /^$/d' infile )
s/^#\+//
remove os hashes principais #
(ocorreu uma ou mais vezes) /^$/d
remove a linha vazia produzida acima, em que uma linha era toda hashes #####
ou remove linhas vazias no arquivo, se houvesse alguma. cut -d'#' -f1
imprime o primeiro campo -f1
quando fileds são delimitados por um hash -d'#'
Ou sed
apenas:
sed 's/^#\+//; /^$/d; s/^\([^#]*\)#.*//' infile
s/^\([^#]*\)#.*//
captura um grupo de partida começando do início da linha para qualquer coisa até que um primeiro hash seja visto e apenas imprima em resultado e ignore o restante. Usando perl
- assumindo apenas #
na entrada como dado na amostra
$ perl -pe 's/[^#]\K#.*|^#//' ip.txt
abc
nrt
clb1aX
amd
[^#]\K#.*
para excluir todos os caracteres da primeira ocorrência de #
se houver um caractere não #
anterior a |^#
caso contrário, remova #
do início da linha
Mesma coisa com sed
$ sed 's/\([^#]\)#.*\|^#//' ip.txt
abc
nrt
clb1aX
amd
Outro sed
sed 's/^#*\([^#]*\).*//' infile
Se você deseja remover linhas apenas com ####
sed 's/^#*\([^#]*\).*//;/^$/d' infile
awk '{sub(/^#/,"")sub(/#/," &");print $1}' file
abc
nrt
clb1aX
amd
Tags awk shell-script cut