manipulação de strings sem awk ou sed

1

qualquer ajuda sobre este problema é apreciada Eu tenho um arquivo de texto com o seguinte formato

Podemos seguramente assumir que os nomes são sempre de três caracteres, profissão 7 caracteres e salário 5 caracteres As variáveis são provenientes da entrada do usuário e não como parâmetros.

BobJanitor20000
TedBuilder30000
NedFighter25000
KitTeacher40000

Peço ao usuário uma entrada de nome e outra entrada para exibir ocupação ou salário

Se o usuário digitar "Ted" e escolher o salário, a saída deverá ser

Ted 30000

O programa também deve levar em conta correspondências parciais de nome, "ed" e salário devem ser emitidos

Ted 30000
Ned 25000

Eu sei que cut e grep podem obter as linhas relevantes, mas como criar a saída que quero?

    
por user3363135 20.10.2015 / 11:41

6 respostas

3

Aqui está um script que funciona para uma pesquisa de nome. Eu estou usando um aqui documento (aka heredoc) em vez de um arquivo externo para entregar a lista para o loop while para que tudo esteja contido neste arquivo para facilitar a leitura. Você pode expandi-lo como quiser.

Leia man bash para informações sobre comandos internos , (e procure no manual por coisas que eu fiz em negrito) que estou usando,

  • Expansão de Substring para obter as partes da linha
  • Correspondência Regular Expression para encontrar a correspondência = ~
  • [[ ...]] para retornar um valor condicional (0 ou 1) dependendo da expressão interna

Aqui está o script:

read -p "Input Name: " SearchName
while read line 
do
  Name=${line:0:3}
  Job=${line:3:7}
  Salary=${line:10:5}
  [[ $Name =~ $SearchName ]] && echo $Name $Salary
done << "end--"
BobJanitor20000
TedBuilder30000
NedFighter25000
end--

user@machine:~/tmp$ bash manipvar.sh 
Input Name: ed
Ted 30000
Ned 25000
user@machine:~/tmp$ 
    
por 20.10.2015 / 13:04
4
$ grep -F ed file|fold -w 5|fold -w 3|grep -E '^[[:upper:]]..|^[0-9]'|paste -sd ' 
$ cut -c 1-3,11- file | grep -F ed | fold -w 3 | paste -sd ' 
$ grep -oE '^.{3}|.{5}$' file | paste -sd ' \n' - | grep -F ed
Ted 30000
Ned 25000
\n' - Ted 30000 Ned 25000
\n' - Ted 30000 Ned 25000

Ou:

separate() {
  fold -w 1 -- "$@" |
    paste -sd '
$ grep -F ed file|fold -w 5|fold -w 3|grep -E '^[[:upper:]]..|^[0-9]'|paste -sd ' 
$ cut -c 1-3,11- file | grep -F ed | fold -w 3 | paste -sd ' 
$ grep -oE '^.{3}|.{5}$' file | paste -sd ' \n' - | grep -F ed
Ted 30000
Ned 25000
\n' - Ted 30000 Ned 25000
\n' - Ted 30000 Ned 25000
separate() {
  fold -w 1 -- "$@" |
    paste -sd '%pre%%pre% %pre%%pre%%pre%%pre%%pre%%pre% %pre%%pre%%pre%%pre%\n' - |
    sort -k 1,1
}

join <(separate file | cut -d ' ' -f 1 | grep -F ed
      ) <(separate file) | cut -d ' ' -f 1,3
%pre%%pre%%pre%%pre%%pre%%pre% %pre%%pre%%pre%%pre%\n' - | sort -k 1,1 } join <(separate file | cut -d ' ' -f 1 | grep -F ed ) <(separate file) | cut -d ' ' -f 1,3

Ou (assumindo o GNU grep ):

%pre%

Você também pode fazer (assumindo um shell com suporte a substituição de processo) algo como:

%pre%     
por 20.10.2015 / 13:56
2

Assumindo que a separação é baseada na letra maiúscula.

com SED

nome + salário

sed -e "/${NamePart}.*[A-Z].*/ !d" -e 's/\([A-Z][a-z]*\)[A-Z][a-z]*\([0-9]*\)/ /' YourData.file

nome + ocupação

sed -e "/${NamePart}.*[A-Z].*/ !d" -e 's/\([A-Z][a-z]*\)\([A-Z][a-z]*\)[0-9]*/ /' YourData.file
    
por 20.10.2015 / 11:56
1

Use este script (puro bash):

#!/bin/bash

# make the search case insensitive
shopt -s nocasematch
unset a; declare -A a

# read the name and save it in $name
read -p "Enter the Name: " name

# read the salary or profession and save it in $type
select type in salary profession;
do
  # loop trough the file
  while read l; do
    # characters 0 to 3 are the name
    n=${l:0:3}
    # the profession and the salary
    a["profession"]="${l:3:7}"
    a["salary"]="${l:10:5}"
    # if the name matches print the selected type
    [[ $n =~ $name ]] && echo "$n ${a[$type]}"
  done <file # the input file
  exit
done

A saída:

$ ./script
Enter the Name: ed
1) salary
2) profession
#? 1
Ted 30000
Ned 25000
$ ./script
Enter the Name: ted
1) salary
2) profession
#? 2
Ted Builder
$ ./script
Enter the Name:
1) salary
2) profession
#? 2
Bob Janitor
Ted Builder
Ned Fighter
Kit Teacher
    
por 20.10.2015 / 13:31
0

Este trabalhou para mim

$ echo 'grep -oe '^...\|[0-9]\{5\}' filename' | grep -oe '.\{9,10\}$\?' | grep ed
Ted 30000 
Ned 25000
    
por 20.10.2015 / 15:26
0

Aqui está uma que funciona meio para trás:

xargs -I{} -n1      \
    expr {}\ {} : '[^0-9]*\(.* .ed\).*'

expr recebe duas cópias de cada linha de back-to-back e é dividido por um espaço como seu primeiro argumento. Como:

expr 'TedBuilder20000 TedBuilder20000' : '[^0-9]*\(.* .ed\).*'

E, assim, os retornos correspondentes - se houver algum - são Salary e, em seguida, Name :

printf %s\n BobJanitor20000 TedBuilder30000 \
             NedFighter25000 KitTeacher40000 |
xargs -I{} -n1      \
    expr {}\ {} : '[^0-9]*\(.* .ed\).*'
30000 Ted
25000 Ned

Isso funciona, no entanto:

xargs sh -c <input  '
      for a do case $a in (?ed*) ! :; esac  ||
            printf  %-4.3s${a##*[!0-9]}\n "$a"
      done' '' 
Ted 30000
Ned 25000
    
por 20.10.2015 / 17:45