Digamos que você tenha um arquivo que contém N colunas delimitadas por espaços em branco e uma coluna adicional que contém espaços que você deseja manter.
Exemplo com N = 2:
1.1 1.2 data for row1
2.1 2.2 data for row2
? ? data for row3
\ * data for row4
Eu gostaria de produzir:
data for row1
data for row2
data for row3
data for row4
No shell você pode fazer isso facilmente com:
while read -r _ _ data
do
printf "%s\n" "$data"
done < data.txt
Mas com awk
isso é meio difícil. Existe um método awk
para dividir apenas as primeiras N colunas?
Se os dados estiverem separados por 1 ou mais espaços, você poderá remover as primeiras 1 ou 2 colunas com sub, onde a coluna é uma única palavra composta por caracteres que não são espaços em branco.
Como seu script de shell de exemplo também removerá a palavra se houver apenas uma palavra, você pode usar uma parte opcional para a segunda palavra.
O padrão corresponde:
^
Início da sequência[[:space:]]*[^[:space:]]+
Combine espaços opcionais e mais de 1 caractere sem espaço em branco([[:space:]]+[^[:space:]]+)?
Opcionalmente, combine 1+ caracteres sem espaço em branco seguidos por 1+ espaços[[:space:]]*
Corresponder espaços finaisEntrada
Saída
Isenção de responsabilidade : esta solução pressupõe que você esteja usando
AWK
o entendimento GNU padrão de campos, ou seja, o separador de campo é um ou mais caracteres de espaço em branco; se isso não for válido, ignore esta resposta completamente.Se você conhece N a priori, você pode preparar uma expressão regular e usá-la em
sub
String Function , nesse particular, deixefile.txt
o conteúdo serentão
dá saída
Explicação: a expressão regular consiste em caracteres de espaço em branco alternados
[[:space:]]
e caracteres que não sejam de espaço em branco[^[:space:]]
, os caracteres de espaço em branco iniciais são opcionais, portanto, há zero ou mais (*
), todos os outros ou 1 ou mais (+
) em número.Se você precisar de uma maneira fácil de ajustar N, use
for
o loop para remover a coluna mais à esquerda, uma por uma, por exemplo, se você desejasse N = 3 e processassefile.txt
como mostrado acima, você poderia fazerque dá saída
Explicação: isso remove a coluna mais à esquerda e o separador de campo adjacente em cada volta do
for
loop.(testado em GNU Awk 5.1.0)
A premissa da linguagem awk é que deve haver apenas construções para fazer coisas que não são fáceis de fazer com outras construções para manter a linguagem concisa e assim evitar o inchaço da linguagem que algumas outras ferramentas/linguagens sofrem. Esta é apenas uma das muitas coisas que seria bom ter uma função para fazer, mas é tão fácil codificar tudo o que você realmente precisa fazer para pular alguns campos para qualquer entrada específica que seria apenas uma confusão a linguagem se existisse uma função para fazer isso e se tivéssemos uma função para ISTO, existem centenas de outras funções que também deveriam ser criadas para fazer todas as outras coisas, seria bom ter uma função para fazer.
Usando GNU awk para
\s/\S
abreviaçãoe o mesmo com qualquer awk POSIX:
Observe que a saída do awk acima reteria qualquer espaço em branco à direita, ao contrário de um loop de leitura do shell.
Ambos dependem de
FS
ser o caractere em branco padrão, mas são facilmente modificados para qualquer outroFS
que possa ser negado em uma expressão de colchetes (ou classe de caractere oposta).Observe que toda a abordagem depende da capacidade de negar a
FS
expressão entre colchetes, para que não funcione se houverFS
algum regexp arbitrário ou mesmo uma string com vários caracteres, mas o loop de leitura do shell que você está pedindo para duplicar também não funcionaria. função de.Se acontecer de você ter um,
FS
você não pode simplesmente negar uma expressão entre colchetes, por exemplo, se seus campos estiverem separados por 3 dígitos ou 2 caracteres de pontuação, você terá algo como:então aqui está uma abordagem mais geral usando GNU awk para o quarto argumento para
split()
: