Je možné nahradiť hodnotu bunky v csv súbor pomocou grep,sed, alebo oboch

0

Otázka

Som napísal nasledovný prí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

Vzorky Vstupného súboru.csv

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

Assuiming $newvalue=3 ,$rownum=4 a col=1, potom vyššie kód nahradí:

Požadovaný Výstup

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

Takže ak by som vedieť riadok a stĺpec, je možné nahradiť povedal hodnotu pomocou grep, sed?

Edit1: Field3 vždy budú mať jedinečnú hodnotu pre svojich radoch. ( v prípade, že info pomáha rovnako)

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

Najlepšiu odpoveď

1

Za predpokladu, že vaše CSV je tak jednoduché, ako to, čo ste ukazujú, (bez čiarky v kótovaných polia) a newvalue neobsahuje znaky, ktoré sed by interpretovať osobitným spôsobom (napr. znakom&, lomky alebo opačné lomítko), tieto by mali pracovať len s sed (testované s GNU sed):

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

Ukážka:

$ 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

Vysvetlivky: $rownum používa sa ako adresu (tu číslo riadka), kde sa uplatňuje nasledovný príkaz. s je sed nahradiť príkaz. [^,]* je regulárny výraz hľadať a nahradiť: najdlhší možný reťazec neobsahujúci čiarkou. $newvalue je nahradenie reťazca. $col je výskyt nahradiť.

Ak newvalue môže obsahovať znakom&, lomky alebo opačné lomítko musíme dezinfikovať to prvé:

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

Ukážka:

$ 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 funguje. Len niekoľko ukazovateľov, aj keď: som si nebol vedomý, že pred touto prosbou o ` [ ^ ,]*", ale ak sed je schopný nahradiť pre konkrétnu bunku, potom prečo sme vrátane [^,]* . Som si vyskúšať sed -Ei "$rownum s/$newvalue/$col" file.csv a to hodil chybu, ale chcel By som vedieť viac o tejto. Akýkoľvek zdroj čítať po by bolo užitočné, rovnako.
Helium

Potrebujeme ` [ ^ ,]*", pretože to je to, čo definuje, čo buniek je. sed nie je CSV procesor, to je akékoľvek-textový procesor. Tak to nemá žiadne vedomosti o tom, čo si zavolať bunky je. Musíme povedať, že je. Sed nahradiť príkaz (s) je vysvetlené v hlbokej podrobnosti v sed manuál, ktorý vám bude ľahko nájsť (ak ste pod GNU/Linux, alebo macOS skúste man sed alebo, ešte lepšie, info sed). Príkaz nahradenia ste sa pokúsili je syntakticky správny, tak chyba.
Renaud Pacalet

Jo, ktorý dáva väčší zmysel teraz, keď uvedenie to ako, že.
Helium
1

S sed, ako sa o:

#!/bin/bash

newvalue=3
rownum=4
col=1

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

Výsledok file.csv

Header,1
Field1,Field2,Field3
1,ABC,4567
3,XYZ,7890
  • ${rownum} zodpovedá číslo riadku.
  • (([^,]+,){n}) zápasy n-čas opakovanie skupiny non-comma znakov, za ktorými nasleduje čiarka. Potom by to malo byť substring pred cieľovým (potrebné ho vymeniť) stĺpec priradením nna col - 1.
2021-11-24 07:21:19

aj keď to funguje, nie je to trochu zložitejšie spôsob, ako robiť veci v porovnaní s ako Renauld odpoveď. Ako dôvod, prečo potrebujeme, aby zodpovedali n-čas opakovanie, keby sme si namiesto toho priamo nahradiť ho? Užitočné napriek tomu
Helium
0

Poďme sa snaží Implementovať sed príkaz

Uvážme vzorky CSV súbor s nasledujúcim obsahom:

$ cat file

Solaris,25,11
Ubuntu,31,2
Fedora,21,3
LinuxMint,45,4
RedHat,12,5
  1. Ak chcete odstrániť 1. pole alebo stĺpec :
$ sed 's/[^,]*,//' file

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

Tento regulárny výraz sa vyhľadáva postupnosť non-čiarka([^,]*) znaky a odstráni ich, ktorého výsledky v 1. poli dostať odstránené.

  1. Ak chcete vytlačiť iba posledné pole, ALEBO odstrániť všetky polia okrem poslednej oblasti:
$ sed 's/.*,//' file

11
2
3
4
5

Tento regulárny výraz odstraňuje všetko do poslednej čiarky(.*,) ktoré majú za následok vymazanie všetkých oblastiach okrem posledného poľa.

  1. Ak chcete vytlačiť iba 1. poľa:
$ sed 's/,.*//' file

Solaris
Ubuntu
Fedora
LinuxMint
RedHat

Tento regulárny výraz(,.*) odstráni znaky od 1. comma do konca následok vymazanie všetkých oblastiach okrem posledného poľa.

  1. Ak chcete vymazať 2. pole:
$ sed 's/,[^,]*,/,/' file

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

Na regulárny výraz (,[^,]*,) vyhľadá čiarkou a postupnosť znakov, po ktorom nasleduje čiarka, ktorej výsledkom zodpovedajúce 2. stĺpec, a nahradí tento vzor sa zhodovali s len čiarka, nakoniec končí v odstránením 2. stĺpec.

Poznámka: Ak chcete odstrániť pole v strede dostane viac tvrdšie v sed, pretože každé pole má byť uzavreté doslova.

  1. Ak chcete vytlačiť iba 2. pole:
$ sed 's/[^,]*,\([^,]*\).*/\1/' file

25
31
21
45
12

Na regulárny výraz zodpovedá prvé pole, druhé pole a zvyšok, avšak skupín 2. pole sám. Celá linka je teraz nahradené 2. pole(\1), teda iba 2. pole dostane zobrazí.

  1. Tlač len tie riadky, v ktorých poslednom stĺpci je jeden miestne číslo:
$ sed -n '/.*,[0-9]$/p' file

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

Na regulárny výraz (,[0-9]$) kontroly pre jednu číslicu do posledného poľa a p príkaz vypíše riadok, ktorý spĺňa túto podmienku.

  1. Na počet všetky riadky v súbore:
$ 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

Toto je simulácia mačka -n príkaz. ispell funguje to jednoducho pomocou špeciálnej premennej NR. V '=' príkaz sed dáva číslo riadka každého riadku nasleduje riadok sám. Sed výstup je odvedený do iného sed príkaz pripojiť každé 2 riadky.

  1. Nahradiť posledné pole 99, ak 1. je pole 'Ubuntu':
$ sed 's/\(Ubuntu\)\(,.*,\).*/\1\299/' file

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

Tento regulárny výraz zápasy 'Ubuntu" a až do konca, okrem posledného stĺpca a skupín, každá z nich rovnako. V náhradný diel, 1. a 2. skupina spolu s novým číslom 99 je podmienkou.

  1. Vymazať 2. pole, ak 1. je pole '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. oblasti, a zostávajúce polia sú zoskupené, a náhrada sa vykonáva len s 1. a posledná skupina , resuting do získania 2. pole zmazané.

  1. Ak chcete vložiť nový stĺpec na konci(posledný stĺpec) :
$ sed 's/.*/&,A/' file

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

Na regulárny výraz (.*) zápasy celý riadok, a nahradiť ju riadok sám (&) a nové oblasti.

  1. Ak chcete vložiť nový stĺpec na začiatku(1. stĺpec):
$ sed 's/.*/A,&/' file

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

Rovnaké ako posledný príklad, len riadok uzavreté nasleduje nový stĺpec

Dúfam, že to pomôže. Dajte mi vedieť, ak potrebujete použiť Ispell alebo akýkoľvek iný príkaz. Ďakujeme

2021-11-24 07:36:29

vďaka za podrobné vysvetlenie, ale bohužiaľ to nie je možné vyriešiť problém v ruke.
Helium

V iných jazykoch

Táto stránka je v iných jazykoch

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