Je možné nahradit hodnotu buňky v csv souboru pomocí grep,sed, nebo obojí

0

Otázka

Napsal jsem následující příkaz

#!/bin/bash
awk -v value=$newvalue -v row=$rownum -v col=1 'BEGIN{FS=OFS=","} NR==row {$col=value}1' "${file}".csv >> temp.csv && mv temp.csv "${file}".csv

Vzorek Vstupní soubor.csv

Header,1
Field1,Field2,Field3
1,ABC,4567
2,XYZ,7890

Assuiming $newvalue=3 ,$rownum=4 a col=1, pak výše uvedený kód nahradí:

Požadovaný Výstup

Header,1
Field1,Field2,Field3
1,ABC,4567
3,XYZ,7890

Tak pokud vím, řádek a sloupec, je možné nahradit řekl hodnotu pomocí grep, sed?

Edit1: Pole3 bude mít vždy jedinečnou hodnotu pro jejich řadách. ( v případě, že info pomůže stejně)

bash csv git-bash linux
2021-11-24 06:52:47
3

Nejlepší odpověď

1

Za předpokladu, že váš CSV soubor je stejně jednoduché jako to, co ukazují (žádné čárky v citovaných oborů), a vaše newvalue neobsahuje znaky, které sed by interpretovat speciálním způsobem (např. ampersandy, lomítka nebo zpětná lomítka), následující by měl fungovat jen s sed (testováno s GNU sed):

sed -Ei "$rownum s/[^,]*/$newvalue/$col" file.csv

Demo:

$ cat file.csv
Header,1
Field1,Field2,Field3
1,ABC,4567
3,XYZ,7890
$ rownum=3
$ col=2
$ newvalue="NEW"
$ sed -Ei "$rownum s/[^,]*/$newvalue/$col" file.csv
$ cat file.csv
Header,1
Field1,Field2,Field3
1,NEW,4567
3,XYZ,7890

Vysvětlení: $rownum je použit jako adresa (zde číslo řádku), kde použít následující příkaz. s je sed nahradit příkaz. [^,]* je regulární výraz hledání a nahrazení: možná nejdelší řetězec neobsahující čárku. $newvalue je náhradní řetězec. $col je výskyt nahradit.

Pokud newvalue může obsahovat ampersandy, lomítka nebo zpětná lomítka musíme dezinfikovat to první:

sanitizednewvalue=$(sed -E 's/([/\&])/\\\1/g' <<< "$newvalue")
sed -Ei "$rownum s/[^,]*/$sanitizednewvalue/$col" file.csv

Demo:

$ newvalue='NEW&\/&NEW'
$ sanitizednewvalue=$(sed -E 's/([/\&])/\\\1/g' <<< "$newvalue")
$ echo "$sanitizednewvalue"
NEW\&\\\/\&NEW
$ sed -Ei "$rownum s/[^,]*/$sanitizednewvalue/$col" file.csv
$ cat file.csv
Header,1
Field1,Field2,Field3
1,NEW&\/&NEW,4567
3,XYZ,7890
2021-11-24 11:13:43

To dělá práci. Jen pár rad: nebyl jsem si vědom, než tato odpověď ` [^,]*` ale jestli sed je schopen nahradit pro konkrétní buňku, tak proč jsme včetně [^,]* . Zkusil jsem to sed -Ei "$rownum s/$newvalue/$col" file.csv a hodilo to chybu, ale chtěli By vědět více o této. Jakýkoli prostředek, aby si na by bylo užitečné, stejně.
Helium

Potřebujeme ` [ ^ ,]*`, protože to je to, co definuje, co mobil je. sed není CSV procesor, to je nějaké-textový procesor. Takže to nemá žádné znalosti o tom, co říkáte cele je. Musíme to říct. Sed nahradit příkaz (s) je vysvětleno v hluboké detaily v sed manuál, který vám bude snadno najít (pokud jste pod GNU/Linux nebo macOS zkusit man sed nebo, ještě lépe, info sed). Náhradní velení jste se snažil je syntakticky nesprávná, tedy chyba.
Renaud Pacalet

Jo, to dává větší smysl teď, když uvedení takového.
Helium
1

S sed,, jak o:

#!/bin/bash

newvalue=3
rownum=4
col=1

sed -i -E "${rownum} s/(([^,]+,){$((col-1))})[^,]+/\\1${newvalue}/" file.csv

Výsledek file.csv

Header,1
Field1,Field2,Field3
1,ABC,4567
3,XYZ,7890
  • ${rownum} zápasy číslo řádku.
  • (([^,]+,){n}) odpovídá n-doba opakování skupiny non-čárka znaky následovaný čárkou. Pak by to mělo být podřetězec před cílem (bude nahrazeno) sloupce přiřazením nk col - 1.
2021-11-24 07:21:19

i když to funguje, není to trochu složitější způsob, jak dělat věci ve srovnání s jak Renauld je odpověď. Jako důvod, proč potřebujeme, aby odpovídaly n-doba opakování-li, můžeme místo přímo nahradit? Užitečné, nicméně
Helium
0

Pojďme se Snažit Provést příkaz sed

Uvažujme vzorek CSV soubor s následujícím obsahem:

$ cat file

Solaris,25,11
Ubuntu,31,2
Fedora,21,3
LinuxMint,45,4
RedHat,12,5
  1. Odstranit 1. poli nebo sloupci :
$ sed 's/[^,]*,//' file

25,11
31,2
21,3
45,4
12,5

Tento regulární výraz vyhledávání pro sekvence non-čárkou([^,]*) znaky a odstraní je, které výsledky v 1. poli získávání odstraněn.

  1. Chcete-li vytisknout pouze poslední pole, NEBO odstranit všechna pole s výjimkou poslední oblasti:
$ sed 's/.*,//' file

11
2
3
4
5

Tento regulární výraz odstraní vše až na poslední čárkou(.*,) které výsledky v odstraňování všech oblastech, až na poslední pole.

  1. Vytiskněte pouze 1. pole:
$ sed 's/,.*//' file

Solaris
Ubuntu
Fedora
LinuxMint
RedHat

Tento regex(,.*) odstraňuje znaky počínaje 1. čárka do konce, což vede k vymazání všech polí s výjimkou posledního pole.

  1. Odstranit 2. pole:
$ sed 's/,[^,]*,/,/' file

Solaris,11
Ubuntu,2
Fedora,3
LinuxMint,4
RedHat,5

Regulární výrazy (,[^,]*,) hledá čárku a posloupnost znaků, následovaný čárkou, které výsledky v odpovídající 2. sloupec, a nahrazuje tento vzor uzavřeno jen s čárkou, nakonec končí v odstranění 2. sloupce.

Poznámka: Chcete-li odstranit pole v blízkém dostane více tvrdší, v sedu, protože každé pole musí být uzavřeno doslova.

  1. Chcete-li vytisknout pouze 2 pole:
$ sed 's/[^,]*,\([^,]*\).*/\1/' file

25
31
21
45
12

Ten regulární výraz se shoduje s první pole, druhé pole a zbytek, nicméně skupiny 2. pole sám. Celá linka je nyní nahrazena 2. pole(\1), tedy pouze 2. pole se zobrazí.

  1. Tisk pouze řádky, v nichž posledním sloupci je jednociferné číslo:
$ sed -n '/.*,[0-9]$/p' file

Ubuntu,31,2
Fedora,21,3
LinuxMint,45,4
RedHat,12,5

Regulární výrazy (,[0-9]$) kontroly pro jednotlivé číslice v posledním poli a p příkaz vytiskne čáru, která odpovídá tomuto stavu.

  1. Na počet všech řádků v souboru:
$ sed = file | sed 'N;s/\n/ /'

1 Solaris,25,11
2 Ubuntu,31,2
3 Fedora,21,3
4 LinuxMint,45,4
5 RedHat,12,5

Tohle je simulace cat -n příkaz. awk se to snadno pomocí speciální proměnné NR. '=' Příkaz sed dává číslo řádku pro každý řádek následovaný řádku sám. Sed výstup je přesměrován do jiného sed příkaz připojit každé 2 řádky.

  1. Nahradit poslední pole 99, pokud 1. pole je 'Ubuntu':
$ sed 's/\(Ubuntu\)\(,.*,\).*/\1\299/' file

Solaris,25,11
Ubuntu,31,99
Fedora,21,3
LinuxMint,45,4
RedHat,12,5

Tento regulární výraz se shoduje 'Ubuntu' a až do konce kromě poslední sloupec a skupiny, každý z nich stejně. Na náhradní díl, 1. a 2. skupiny spolu s novým číslem 99 je nahradit.

  1. Odstranit 2nd pole, pokud 1. pole je 'RedHat':
$ sed 's/\(RedHat,\)[^,]*\(.*\)/\1\2/' file

Solaris,25,11
Ubuntu,31,2
Fedora,21,3
LinuxMint,45,4
RedHat,,5

1. pole 'RedHat', 2. pole a zbývající pole jsou seskupeny, a výměna se provádí pouze s 1. a poslední skupina , resuting v získání 2. pole odstraněny.

  1. Chcete-li vložit nový sloupec na konci(poslední sloupec) :
$ sed 's/.*/&,A/' file

Solaris,25,11,A
Ubuntu,31,2,A
Fedora,21,3,A
LinuxMint,45,4,A
RedHat,12,5,A

Regulárního výrazu (.*) zápasy celé linky a nahradí ji linka sám (a) a nové pole.

  1. Chcete-li vložit nový sloupec na začátek(1. sloupec):
$ sed 's/.*/A,&/' file

A,Solaris,25,11
A,Ubuntu,31,2
A,Fedora,21,3
A,LinuxMint,45,4
A,RedHat,12,5

Stejně jako minulý příklad, jen linka uzavřeno následuje nový sloupec

Doufám, že to pomůže. Dejte mi vědět, pokud budete muset použít Awk nebo jakýkoli jiný příkaz. Děkuji

2021-11-24 07:36:29

díky za podrobné vysvětlení, ale bohužel to neřeší problém.
Helium

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................