มันเป็นไปได้แทนที่ค่าของห้องขังอยู่ในแฟ้ม csv แฟ้มโดยใช้ grep,sed หรือทั้งสอง

0

คำถาม

ฉันต้องเขียนที่ตามคำสั่ง

#!/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

ตัวอย่างข้อมูลของ แฟ้มได้แฟ้ม csv

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

Assuiming $newvalue=3,$rownum=4 แล้ว col=1,งั้นที่อยู่เหนือหัสจะมาแทน:

ต้องการแสดงผล

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

ดังนั้นถ้าฉันรู้ว่าแถวและสดมภ์มันจะเป็นไปได้ต้องการจะแทนที่บอกว่าค่าใช้ grep,sed?

Edit1:Field3 จะมีเฉพาะตัวและงานเพียงอย่างเดีค่าสำหรับพวกเขา respective แถว. (ในกรณีที่ข้อมูลจะช่วยยังไงก็ตา)

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

คำตอบที่ดีที่สุด

1

คิดว่าของแฟ้ม csv แฟ้มง่ายอย่างที่คุณแสดง(ไม่มี commas ในส่วนที่อ้างถึงช่องข้อมูล)และของคุณ newvalue ไม่มีตัวอักษรที่ sed จะตีความเรื่องในวิธีพิเศษ(e.g. ampersands,slashes หรือ backslashes)ที่ตามต้องทำงานให้กับครอบ sed(ทดสอบกับ GNU sed):

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

สาธิต:

$ 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

คำอธิบายได้หลายทาง: $rownum คือใช้เป็นที่อยู่(อยู่ในเส้นจำนวน)อยู่ไหนไปใช้งานตามคำสั่ง. s คือ sed สอนแทนสั่ง [^,]* คือเงื่อนไขการค้นหาสำหรับค้นหาและแทนที่นานที่สุดเป็นไปได้ข้อความไม่ได้บรรจุเป็นคอมม่า $newvalue เป็นการแทนที่ข้อความ $col คืนที่เกิดจะแทนที่.

ถ้า newvalue อาจจะมี ampersands,slashes หรือ backslashes เราต้อง sanitize มันแรก:

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

สาธิต:

$ 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

นี่มันงาน แค่คนสอนเรื่องสำคัญๆถึงแม้ว่าฉันไม่ทราบก่อนหน้านี้คำตอบของ`[^,]*`แต่ถ้า sed สามารถแทนที่สำหรับเฉพาะมือถือแล้วทำไมเราต้องรวมถึ[^,]*. ฉันพยายาม sed -Ei "$rownum s/$newvalue/$col" file.csv และมันทิ้งข้อผิดพลาดเกิดขึ้นระหว่างแต่อยากจะรู้มากกว่านี้เกี่ยวกับเรื่องนี้ มีทรัพยากรที่จะอ่านท่านจะต้องการความช่วยเหลือเหมือนกัน
Helium

เราต้องการ`[^,]*`เพราะมันคือสิ่งที่บ่งบอกสิ่งที่ มือถือ นะ sed ไม่ใช่แฟ้ม csv หน่วยประมวลผล name มันคืออะไร-ข้อความหน่วยประมวลผล name. ดังนั้นมันไม่มีความรู้ของสิ่งที่คุณโทรหา มือถือ นะ เราต้องบอกด้วย ที่ sed สอนแทนคำสั่ง(s)เป็นอธิบายในรายละเอียดลึกอยู่ใน sed คู่มือนที่คุณจะได้ค้นหา(หากคุณอยู่ภายใต้ GNU/ระบบลินุกซ์หรือ macOS พยายาม man sed หรือแม้แต่ดีกว่านี้ info sed). ครูตัวแทนขอสั่งคุณพยายามเป็น syntactically ไม่ถูกต้อง,ดังนั้นข้อผิดพลาด
Renaud Pacalet

ใช่นั่นก็สมเหตุสมผลตอนนี้เมื่อทำมันอย่างนั้น
Helium
1

กับ sedยังไงเรื่อง:

#!/bin/bash

newvalue=3
rownum=4
col=1

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

ผลลัพธ์ของ file.csv

Header,1
Field1,Field2,Field3
1,ABC,4567
3,XYZ,7890
  • ${rownum} ตรงกับที่สายเบอร์
  • (([^,]+,){n}) ตรงกับ n-เวลาเป็นสัญลักษณ์แห่งของกลุ่ม ไม่ใช่จุลภาคตัวอักษรตามโดยคอมม่า งั้นมันควรเป็นส่วนข้อความอยู่ว่า ก่อนที่เป้าหมาย(ต้องเป็น substituted)คอลัมน์โดยกำลังกำหนด nต้อง col - 1.
2021-11-24 07:21:19

ถึงแม้ว่ามันทำงานไม่ใช่สักหน่อมากกว่าซับซ้อนทางของการทำเรื่องเมื่อเทียบกับยังไง Renauld เป็นคำตอบ เหมือนทำไมเราต้องตรงกับ n-เวลาเป็นสัญลักษณ์แห่ถ้าเราสามารถแทนที่จะเป็นข้อเขียนทับมันหรือไม่? ช่วยยังไงก็ตาม
Helium
0

ปล่อยให้เป็นพยายามที่จะดำเนิ sed คำสั่ง

ปล่อยให้พวกเราพิจารณาตัวอย่างแฟ้ม csv แฟ้มกันตามเนื้อหาภายใน:

$ cat file

Solaris,25,11
Ubuntu,31,2
Fedora,21,3
LinuxMint,45,4
RedHat,12,5
  1. ต้องลบหน่วยที่ 1 ก็สนามหรือคอลัมน์:
$ sed 's/[^,]*,//' file

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

นี่เงื่อนไขการค้นหาสำหรับอนุกรมของคนที่ไม่ใช่จุลภาค([^,]*)ตัวอักษรและลบพวกเขาซึ่งผลอยู่ในหน่วยที่ 1 ก็สนามจะถูกลบออกไป

  1. ที่จะพิมพ์เฉพาะจดหมายที่ได้รับล่าสุดสนามหรือลบทุกช่องข้อมูลยกเว้นคนสุดท้ายช่องข้อมูล:
$ sed 's/.*,//' file

11
2
3
4
5

นี่ regex เอาทุกอย่างจนคนสุดท้ายจุลภาค(.*,) ซึ่งผลอยู่ในการลบช่องข้อมูลทั้งหมดยกเว้นคนสุดท้ายสนาม

  1. เพื่อพิมพ์เดียวที่หน่วยที่ 1 ก็ช่องข้อมูล:
$ sed 's/,.*//' file

Solaris
Ubuntu
Fedora
LinuxMint
RedHat

นี่ regex(,.*) เอาที่ตัวอักษรเริ่มต้นจากหน่วยที่ 1 ก็จุลภาคมจนกว่าจะสิ้นผลลัพธ์จากอยู่ในการลบช่องข้อมูลทั้งหมดยกเว้นคนสุดท้ายสนาม

  1. แบบอักษรเพื่อทำการลบ 2 ช่องข้อมูล:
$ sed 's/,[^,]*,/,/' file

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

ที่ regex(,[^,]*,)การค้นหาสำหรับจุลภาคงและลำดับของตัวอักษรตามด้วยจุลภาคซึ่งผลตรวจในตรงกับคน 2 คอลัมน์และก็แทนนี้รูปแบบตรงกับกับจุลภาค,ตอนจบท้ายที่สุดในการลบ 2 คอลัมน์

ข้อควรจำ:จะลบช่องข้อมูลในตอนกลางจะยิ่งยากขึ้นใน sed ตั้งแต่ทุกสนามต้นตรงกันกับเหมือนจะเป็นความจริง

  1. เพื่อพิมพ์เดียวที่ 2 ช่องข้อมูล:
$ sed 's/[^,]*,\([^,]*\).*/\1/' file

25
31
21
45
12

ที่ regex ตรงกับที่ก่อสสอนภาคสนามแล้วที่เหลืออย่างไรก็ตามกลุ่ม 2 ทุ่งอยู่คนเดียว คนทั้งหมดคือตอนนี้แทนที่ด้วยที่ 2 ทุ่(\1)จึงเพียง 2 ทุ่ถูกแสดง

  1. พิมพ์เดียวที่อยู่ในบรรทัดซึ่งคนสุดท้ายคอลัมน์เป็นโสดตัวเลขจำนวน:
$ sed -n '/.*,[0-9]$/p' file

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

ที่ regex(,[0-9]$)เช็คสำหรับตัวเลขเดียวในสนามและค p คำสั่งรอยนิ้วมือเส้นซึ่งตรงกับเงื่อนไขนี้.

  1. ต้องจำนวนทุกบรรทัดอยู่ในแฟ้ม:
$ 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

นี่เป็นการจำลองของแมว-n กองบัญชาการ ภาษาโปรแกรม awklanguage section มันได้ง่ายๆโดยใช้ตัวแปรเป็นพิเศษลำดับ@label. กรอง'='คำสั่งของ sed ทำให้เส้นจำนวนของทุกๆสายตามด้วยสายตัวมันเอง ที่ sed ผลส่งออกเป็น piped อีก sed คำสั่งที่จะเข้าร่วมกับทุก 2 แล้วเราพลาดอะไรไปเนี่ย?

  1. แทนที่สุดท้ายที่สนามโดย 99 ถ้าหน่วยที่ 1 ก็ช่องข้อมูล'Ubuntu':
$ sed 's/\(Ubuntu\)\(,.*,\).*/\1\299/' file

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

นี่ regex ตรงกับ'Ubuntu'และจนกระทั่งสิ้นยกเว้นคนสุดท้ายคอลัมน์และกลุ่มกันของพวกเขาเช่นกัน ในการแทนที่ส่วนที่ 1 และ 2 กลุ่มพร้อมกับคนใหม่เลข 99 คือ substituted.

  1. ลบ 2 ทุ่ถ้าหน่วยที่ 1 ก็ช่องข้อมูล'@label:listbox kde distribution method':
$ sed 's/\(RedHat,\)[^,]*\(.*\)/\1\2/' file

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

หน่วยที่ 1 ก็สนาม'@label:listbox kde distribution method'ที่ 2 ทุ่งและที่เหลือช่องข้อมูลรวมกลุ่มและเปลี่ยนที่นี่จบเรื่องเดียวที่ 1 และเมื่อกลุ่ม resuting ในที่ 2 ทุ่งโดนลบ

  1. จะแทรกใหม่คอลัมน์ที่สุด(เมื่อคอลัมน์):
$ sed 's/.*/&,A/' file

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

ที่ regex(.*) ตรงกับคนทั้งสายออกและแทนที่มันที่บรรทัดที่ตัวมันเอง(&)และใหม่ของสนาม

  1. จะแทรกใหม่คอลัมน์ในการเริ่มต้น(1 คอลัมน์):
$ sed 's/.*/A,&/' file

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

เหมือนกับเมื่อตัวอย่างเช่นนแค่เส้นตรงกับเป็นตามโดยคอลัมน์แสดงผล view->

ฉันหวังว่านี่จะช่วยได้ บอกให้ฉันรู้ถ้าคุณต้องการที่จะใช้ภาษาโปรแกรม awklanguage section หรืออะไรอีกกองบัญชาการ ขอบคุณ

2021-11-24 07:36:29

ขอบคุณสำหรับกล่องแสดงรายละเอียดคำอธิบายแต่โชคร้ายที่มันไม่ได้แก้ปัญหาของกันเลยดีกว่า
Helium

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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