Aiuto Awk - Grep - Sed

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

spina ha scritto:Ma mi dovresti dire il formato, esatto. Ma perché, datetime(?) non va bene?

Emanuele
Uso datetime perchè tenendo nel database degli appuntamenti da svolgere ho anche bisogno dell'orario dell'appuntamento..
Ma questa è solo una "new entry", per le vecchie date importate dal file vcf non sapendo l'orario si
potrebbero inserire tutte per le 12...
Il formato esatto è questo: '2012-05-22 12:00:00' come saprete

Vi ringrazio tantissimo
Francesco :D

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

Ti ho diviso la data in 'gg' 'mm' 'aa' (sono nell'array 'gma'). Occhio che do per scontato che le date siano tutte dal 2000 in poi, dato che c'è solo l'anno nella vcard, io ci ho aggiunto un '20' davanti. Come orario ci ho messo sempre '00:00:00' e ti ho quotato il tutto:

Codice: Seleziona tutto

/FN:/{
  gsub(/[[:space:]]+/, " ", $0);
  sub(/FN:/, "", $1);

  nome=$1;
  for ( i=2; i < NF; i++ )
    nome=nome " " $i;
  cognome=$NF;

  printf "insert into clienti (.....) Values (%s, %s)\n", nome, cognome;
}

/NOTE:/{
  sub(/NOTE:/, " ", $0);

  do
    {
      if ( match($0, /^ /) == 0 )
        break;
      sub(/^ */, "", $0);
      note=note $0;
      getline;
    }
  while ( 1 );

  gsub(/[[:space:]]+/, " ", note);
  sub(/\\n/, "", note);
  gsub(/\\\" */, " ", note);

  split(note, appuntamenti, " ");
  for ( a in appuntamenti )
    {
      match(appuntamenti[a], /^([^-]*)-([^\(]*)\(([^\)]*)\).*$/, info)
      # info[1] == data, info[2] == id_trattamento, info[3] == id_dipendente
      split(info[1], gma, ".");
      # gma[1] == giorno, gma[2] == mese, gma[3] == anno
      printf "insert into appuntamenti (id_cliente, %s, %s, '20%s-%s-%s 00:00:00')\n",
        info[3], info[2], gma[3], gma[2], gma[1];
    }
}
a me come output da (sull'unica entry che hai messo ad inizio thread):

Codice: Seleziona tutto

insert into clienti (.....) Values (Adele, Xxxxeri)
insert into appuntamenti (id_cliente, 4, 2, '2011-01-22 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2011-02-12 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2011-03-05 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2011-03-26 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2011-04-23 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2010-11-16 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2010-12-09 00:00:00')
insert into appuntamenti (id_cliente, 4, 2, '2010-12-30 00:00:00')
Comunque io ritorno dire che te ne fai poco di queste cose se ti server un'istruzione sql per prelevare l'id del cliente appena inserito.
Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

spina ha scritto:quindi alcune note:
  • probabilmente i valori vanno quotati nella query sql;
  • il formato della data va modificato se il campo del database è di tipo 'date';
  • l'id del cliente lo devi prelevare attraverso una query che però dipende dal DBMS su cui stai lavorando. Ad esempio, MySQL mette a disposizione il metodo LASTE_INSERT_ID() che dovresti eseguire dopo la insert in 'clienti';
.....
Comunque io ritorno dire che te ne fai poco di queste cose se ti server un'istruzione sql per prelevare l'id del cliente appena inserito.
Emanuele
Su tua dritta mi sono visto la funzione LASTE_INSERT_ID() :D
ed ho modificato al volo il tuo script

Ho cambiato provvisoriamente solo l'output da produrre nelle printf così

Codice: Seleziona tutto

printf "insert into clienti values (null, '%s', '%s', 'telefono', null);\n",nome, cognome;
printf "insert into  appuntamenti VALUES  ( null , '20%s-%s-%s 00:00:00', 'descrizionecognomeesempio', LAST_INSERT_ID(), %s );\n", gma[3], gma[2], gma[1], info[3];
L'unico problema e che molte date non vanno perche nel file di origine, il campo NOTE,
al 75esimo carattere và a capo dividendo le date cosi...

Codice: Seleziona tutto

NOTE:16.11.10-2(4)\" 09.12.10-2(4)\" 30.12.10-2(4)\" 22.01.11-2(4)\" 12.02.
 11-2(4)\" 05.03.11-2(4)\" 26.03.11-2(4)\" 23.04.11-2(4)\"\n
Ora provo a mettere il campo NOTE su una sola riga e collegare le stringe togliendo lo spazio della riga successiva
e poi provo ad estrapolare anche il campo telefono e passarlo ad una variabile per il campo cliente..

Conoscete qualche bella guida possibilmente in italiano per awk e sed così da poter provare a risolvere da solo?

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

Ma guarda che questa evenienza l'avevo già sistemata io. Infatti se guardi l'output che ti ho postato prima le date sono corrette.

Però LAST_INSERT_ID ti ritorna l'ultimo id inserito, ciò vuol dire che dopo che avrai inserito un appuntamento, LAST_INSERT_ID ti ritornerà l'id di questo appuntamento e non più del cliente.

Secondo me devi fare tutto via PHP, così ti puoi salvare l'id del cliente in una variabile.
Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

spina ha scritto: Secondo me devi fare tutto via PHP, così ti puoi salvare l'id del cliente in una variabile.
Emanuele
L'ho fatto non funziona come dovrebbe :evil:
Per ora mi sono limitato solo ad inserire il cliente e vedere se riuscivo a salvare l'ultimo id aggiunto

Codice: Seleziona tutto

<?php
include("connessione.php");
  $file = fopen("contacts2.vcf", "r" )or die ("Non posso aprire il file");
  while (! feof($file))
  {
    $line=fgets($file, 1024);

    if ( (substr($line,0,2) == "FN") )
    {
      $nome_cognome=substr($line, 3);
      $nome_array = explode(" ", $nome_cognome);
      if ($nome_array[0] == "") $nome_array[0] = "Sconosciuto";
      if ($nome_array[1] == "") $nome_array[1] = "Sconosciuto";    
    }
    if ( substr($line, 0,3) == "TEL")
      $telefono= substr($line,14);

    if (isset($nome_array[0]) && isset($nome_array[1]) && isset($telefono) )
    {
      /*print "INSERT INTO clienti VALUES (NULL, '$nome_array[0]','$nome_array[1]','$telefono', NULL);"; */

      $query=mysql_query("INSERT INTO clienti VALUES (NULL, '$nome_array[0]','$nome_array[1]','$telefono', NULL);");
      if($query == FALSE) print "<BR>Errore nell'inserimento dell'utente: '$nome_array[0]', '$nome_array[1]'";
      else print "<BR>Inserimento dell'utente: '$nome_array[0]', '$nome_array[1]' riuscito";
      $idcliente=mysql_insert_id();
      print "<BR>Ultimo ID cliente inserito = $idcliente";
      unset($nome_array[0]); unset($nome_array[1]); unset($telefono);
    }
    
    /*PARTE DOVE AGGIUNGO I VARI APPUNTAMENTI*/
   /*DA FINIRE*/
      if (substr($line,0,4) == "NOTE") 
      {
	$note=substr($line,5);
      }else
	if (substr($line,0,1) == " ") /*CONTINUO DI NOTE*/
	{
	  $note2 = substr($line, 0);
	}
	
	if ( isset($note) && isset($note2) )
	{
	  trim ($note);trim($note2);
	  $notacompleta= $note."".$note2;
	  $appuntamenti = explode("\\\"", $notacompleta); //DIVIDO E CICLO PER OGNI APPUNTAMENTO eSEMPIO: 07.08.12-2(9)\" 
	  for($j=0;$j<count($appuntamenti);$j++)
	    {
	      $info= explode("-",$appuntamenti[$j]); //DIVIDO APPUNTAMENTO IN DATA - PRESTAZIONE - DIPENDENTE
	      $data=$info[0];
	      //SEPARO LA DATA
	      $divdata = explode(".",$data);
	      /* Giorno=$divdata[0] - Mese=$divdata[1] - Anno=$divdata[2]";*/
	      //SEPARO DIPENDENTE E PRESTAZIONE
	      $dip_pre = explode("(",$info[1]);
	      $dipendente=$dip_pre[0];
	      $prestazione=substr($dip_pre[1],0,1);
	      
	      /*AGG CONTROLLO SE DIPENDENTE=[0-9] && PRESTAZIONE=[0-9] && DATA E' ESATTA SCRIVI*/
	      echo "<BR>INSERT INTO appuntamenti VALUES  ( null , '$divdata[2]-$divdata[1]-$divdata[0] 00:00:00', 'descrizionecognomeesempio', LAST_INSERT_ID(clienti), $dipendente, $prestazione);\n";

	    }
	  print "Cliente successivo<BR><BR><BR><BR>";
	  unset($note);unset($note2);
	}
	
  }
    
    ?>
Se eseguo la pagina in php mi aggiunge il record così:

Codice: Seleziona tutto

mysql> select * from clienti;
+----+----------+-----------------+--------------+---------------+
| id | nome     | Cognome         | Telefono     | Via           |
+----+----------+-----------------+--------------+---------------+
|  1 | cliente1 | cognomecliente1 | 345435467    | marginesu 20  |
|  2 | cliente2 | cognome2        | 32334444     | vaiiiii       |
| 17 | Adele    | MXXXXX
 | NULL          |84
+----+----------+-----------------+--------------+---------------+
8 rows in set (0.00 sec)
Mentre se invece faccio solo stampare la query, e la eseguo da mysql
i dati vengono inseriti correttamente..

Sapete dirmi il perchè????

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

Probabilmente è sempre lo stesso problema con i caratteri non stampabili di DOS. Devi ripulire la stringa letta dal file per sostituire una serie di caratteri non stampabili con un singolo spazio.

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

Mi sapresti dire quale espressione posso usare per indicare qualsiasi carattere non stampabile?????
Grazie ;)

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

Dovrebbe bastare sostituire la riga:

Codice: Seleziona tutto

$line=fgets($file, 1024);
con:

Codice: Seleziona tutto

$line=preg_replace('/[[:space:]]+/', ' ', fgets($file, 1024));
Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

Ahahahaha Funzionaaaaa!!!!
Ne sai troppo!!!! ;D

E io che mi stavo azzuffando per cambiare il fileformat con vim.... :cry:

Adesso provo ad aggiungere anche gli appuntamenti :D
Se riesco faccio sapere
Grazièèèèèè :D

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

Ho un'altra domanda :roll:
Sto leggendo un file in php con fgets.
Mi sapete dire se è possibile leggere la riga successiva a quella in lettura in quel momento???
In pratica leggo il file riga per riga ma prima di leggere la riga attuale vorrei sapere se la riga successiva è di un certo tipo
mi sapete dire se è possibile???

Grazie ;)

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

L'approccio mi sembra sbagliato. Devi fare un'automa a stati finiti. Più o meno l'algoritmo che devi seguire è questo:

Codice: Seleziona tutto

leggi riga
setta_stato
switch(stato)
  FN:...
  NOTE:...
...
dove la routine "setta_stato" si deve preoccupare anche di ripulire la riga letta. In questo modo, se la riga che stai leggendo è il seguito di una precedente, allora setta stato lascerà la variabile 'stato' inalterata e si limiterà a ripulire la riga (ad esempio eliminando gli spazi iniziali).
Spero di essermi spiegato bene, altrimenti, se posti il codice lo guardiamo insieme.

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

Giustissimo... così è molto più semplice e più ordinato :D
Questo è come l'ho iniziato a fare, è solo la base,
mancano le vecchie prassi che trasformano la data e eseguono le query
ma rende l'idea... :

Codice: Seleziona tutto

<?php
  $file = fopen("contacts.vcf", "r" )or die ("Non posso aprire il file");
  $stato = 0;
  while (! feof($file))
  {
    $riga=preg_replace('/[[:space:]]+/', ' ', fgets($file, 1024));
    if ( substr($riga,0,2) == "FN")  $stato=1;
    if (substr($riga,0,3) == "TEL" ) $stato=2;
    if ( substr($riga,0,4) == "NOTE") $stato=3;
    if ( substr($riga,0,3) == "END") $stato=4;
    switch($stato)
    {
      case 1:
	$nome_cognome=substr($riga, 3);
	$nome_array = explode(" ", $nome_cognome);
	if ($nome_array[0] == "") $nome_array[0] = "Sconosciuto";
	if ($nome_array[1] == "") $nome_array[1] = "Sconosciuto";
	$stato=0;
	break;
      case 2:
	$telefono= substr($riga,14);
	print "<br><FONT color=BLUE>Utente  '$nome_array[0]','$nome_array[1]','$telefono' </FONT>";
	//unset($nome_array);unset($nome_cognome);unset($telefono);
	$stato=0;
	break;
      case 3:
	if(isset($note)) $note= $note."".$riga;
	else $note=substr($riga,5);
	break;
      case 4:
	$note=str_replace(" ", "", $note);
	print "<br><FONT color=RED>$note</FONT>";
	$stato=0;
	unset($note);
	break;
    }

  }	
?>
Ora funziona alla grande :D
Grazie 1000

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

E' più o meno come l'avevo immaginato io, solo che:
  • nei case non hai bisogno di resettare lo stato, l'idea è che se gli if iniziali identificano un nuovo stato, si cambia, altrimenti si rimane nel vecchio stato (continuazione di riga);
  • negli if iniziali devi anche identificare la continuazione di riga (la riga inizia con uno spazio, nell'esempio che hai postato al primo post);
  • gli if iniziali dovrebbero essere "if, else if". Altrimenti ogni volta fai tutti i controlli, e non serve;
  • prima dello switch devi anche ripulire la riga, questo va fatto negli if. Ad esempio, nel case 1 tu fai:

    Codice: Seleziona tutto

    $nome_cognome=substr($riga, 3);
    per eliminare l'FN:, ma questo va fatto negli if, il case 1 deve solo fare quello che deve fare (prelevare nome e cognome);
Ma perché usi i tag HTML? Se esegui lo script semplicemente con:

Codice: Seleziona tutto

php script.php
non serve un output formattato per un browser.

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Aiuto Awk - Grep - Sed

Messaggio da targzeta »

Eccoti l'idea che avevo in mente. Ti ho messo dei TODO che non ho fatto (sono dei placeholder per dove immagino debbano essere fatte le cose).

Codice: Seleziona tutto

<?php
$file = fopen('contacts.vcf', 'r' ) or die ('Non posso aprire il file');

// TODO: collegarsi al database

function _reset()
{
  global $stato, $nome, $cognome, $telefono, $note;

  $stato = 0;
  $nome = $cognome = 'Sconosciuto';
  $telefono = $note = '';
}

_reset();
while (! feof($file))
  {
    $riga = preg_replace('/[[:space:]]+/', ' ', fgets($file, 1024));

    if ( substr($riga,0,2) == 'FN' )
      $stato = 1;
    elseif ( substr($riga,0,3) == 'TEL' )
      $stato = 2;
    elseif ( substr($riga,0,4) == 'NOTE' )
      $stato = 3;
    elseif ( substr($riga,0,3) == 'END' )
      $stato = 4;
    elseif ( substr($riga, 0, 1) != ' ')
      continue;

    $riga = trim(preg_replace('/^[^:]*:/', '', $riga));
    switch ( $stato )
      {
      case 1:
        $tmp = explode(' ', $riga);
        $tmp_size = count($tmp);
        if ( $tmp_size == 1 && $tmp[0] != '' )
          $nome = $tmp[0];
        elseif ( $tmp_size > 1 )
          {
            $cognome = array_pop($tmp);
            $nome = implode(' ', $tmp);
          }
        break;
      case 2:
        $telefono .= $riga;
        break;
      case 3:
        $note .= $riga;
        break;
      case 4:
        print 'Nome: ' . $nome . "\n"
          . 'Cognome: ' . $cognome . "\n"
          . 'Telefono: ' . $telefono . "\n"
          . 'Note: ' . $note . "\n\n";

        // TODO: INSERT nel database

        _reset();
        break;
      }
  }

fclose($file);
// TODO: terminare connessione al database
?>
eseguilo come:

Codice: Seleziona tutto

php script.php
Ricorda che l'interprete PHP se incontra una stringa che inizia con i doppi apici (") si mette ad interpretarla perché all'interno potrebbe trovare variabili o caratteri non stampabili. Quindi se devi scrivere una stringa pura, tipo: 'Non posso aprire il file', è meglio se la metti tra apici singoli (').

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 657
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: Aiuto Awk - Grep - Sed

Messaggio da darkstaring »

Si, è molto simile...
Comunque non capisco perchè aggiungere il controllo

Codice: Seleziona tutto

    elseif ( substr($riga, 0, 1) != ' ')
      continue;
Non basta l' "elseif ( substr($riga,0,3) == 'END' )" per trovare la fine delle note ????

Rispondi