[英]awk function to modify several columns with regex in a csv
目标:
我需要修改网址以仅保留其中的数字(纬度/经度/ID):在 .csv 文件中,我有一个“标题中的某些标题”。 这个我需要找到。 在此找到的 Titel 列中,我需要删除 url 的开头和结尾,因此只留下一个数字,即 url 的一部分。 这需要在不同的结构化 csv 上执行,其中有几列具有不同的标题和不同的 url 模式。 有没有办法用 awk 在 bash 中编写函数?
我试过 - 但它不起作用,因为它缺少很多缺失的知识:
#!/bin/bash
CSVFILE=$(find ./aufzubereiten -type f ! -name ".DS_Store") #only one file in this folder.
FILENAME=$(basename "$CSVFILE")
function modify_col() {
COL= how to find the right column in the csv?
awk -F',' OFS="," -v pat='"$PAT"' '{sub(/pat/,X,$${COL})} 1' "$CSVFILE" > "$CSVFILE".tmp1 && mv "$CSVFILE".tmp1 "$CSVFILE"
}
COLTITEL="certain Titel in Header"
PAT='/Text1234Text[0-9]{5,8}Text1.html'
PATNEW=''
modify_col
COLTITEL="certain Titel2 in Header"
PAT='/Text2234Text[0-9]{5,8}Text2.html'
PATNEW=''
modify_col
COLTITEL="certain Titel3 in Header"
PAT='/Text3234Text[0-9]{5,8}Text3.html'
PATNEW=''
modify_col
示例文件:
header1, header2, certain Titel in Header, certain Titel2 in Header, certain Titel3 in Header
,,/Text2234Text7846641Text.html,/Text2234Text8974341Text2.html,/Text2234Text823241Text3.html
,,/Text2234Text7846642Text.html,/Text2234Text8974342Text2.html,/Text2234Text823242Text3.html
,,/Text2234Text7846643Text.html,/Text2234Text8974343Text2.html,/Text2234Text823243Text3.html
结果应该是:
header1, header2, certain Titel in Header, certain Titel2 in Header, certain Titel3 in Header
,,7846641,8974341,823241
,,7846642,8974342,823242
,,7846643,8974343,823243
谢谢你的想法:)
您能否尝试使用所示示例进行以下、编写和测试。
awk '
BEGIN{
FS=OFS=","
}
FNR==1{
print
next
}
{
for(i=1;i<=NF;i++){
sub(/^\/Text[0-9]+Text/,"",$i)
sub(/Text.*/,"",$i)
}
}
1
' Input_file
说明:添加对上述代码的详细说明。
awk '
BEGIN{ ##Starting BEGIN section of code here.
FS=OFS="," ##Setting FS and OFS to comma here.
}
FNR==1{ ##Checking condition if FNR==1 then do following.
print ##Printing the current line here.
next ##next will skip all further statements from here.
}
{
for(i=1;i<=NF;i++){ ##Starting a for loop to traverse into all fields here.
sub(/^\/Text[0-9]+Text/,"",$i) ##Substituting from starting Text digits Text with NULL in current field.
sub(/Text.*/,"",$i) ##Substituting everything from Text to till last of field value with NULL in current field.
}
}
1 ##1 will print edited/non-edited line here.
' Input_file ##Mentioning Input_file name here.
假设:
Text
显示在每个html
文件名中的 3x 位置样本数据:
$ cat text.dat
header1, header2, certain Titel in Header, certain Titel2 in Header, certain Titel3 in Header
,,/Text2234Text7846641Text.html,/Text2234Text8974341Text2.html,/Text2234Text823241Text3.html
,,/Text2234Text7846642Text.html,/Text2234Text8974342Text2.html,/Text2234Text823242Text3.html
,,/Text2234Text7846643Text.html,/Text2234Text8974343Text2.html,/Text2234Text823243Text3.html
一种awk
解决方案:
$ awk -F"Text" '
BEGIN { OFS="," }
FNR==1 { print ; next }
{ print ",,"$3,$6,$9 }
' text.dat
在哪里:
-F"Text"
- 使用Text
作为我们的输入字段分隔符OFS=","
- 设置输出字段分隔符FNR==1 {print ; next}
FNR==1 {print ; next}
- 对于第 1 行(标题行)打印整行并跳到文件中的下一行print ",,"$3,$6,$9
- 打印 2 个逗号,然后是字段 3、6 和 9(由OFS=","
分隔)结果:
header1, header2, certain Titel in Header, certain Titel2 in Header, certain Titel3 in Header
,,7846641,8974341,823241
,,7846642,8974342,823242
,,7846643,8974343,823243
这是查找五位或更多位数字并删除其他所有数字的通用解决方案。
awk -F , 'BEGIN { OFS=FS }
FNR>1{
for(i=1;i<=NF;++i) {
gsub(/(^|[^0-9])[0-9]{1,4}([^0-9]|$)/, "", $i);
gsub(/[^0-9]+/, "", $i);
}
} 1' filename
如果您只有一个文件名,则可能没有理由使用find
。 如果您不知道文件名但当前目录中只有一个文件, *
将扩展为该文件名。
这有点脆弱,因为如果一个字段中的两个数字被一个非数字字符分隔,它就不会做正确的事情。 解决这个问题并不难,但我很懒,你的要求有点模糊。
我知道 OP 询问是否有办法使用 awk 来实现它,但是从上下文提供的内容来看,我知道任何可以在 bash 脚本中运行的解决方案都可以解决 OP 的问题。
对于这种情况,我相信sed
是一个更优雅的解决方案:
sed 's/[^,]\+[^0-9]\([0-9][0-9]\+\)[^,]\+/\1/g' data.csv
它输出任何接近字段末尾的 2 位或更多位数字。 sed
的扩展版本可能有助于更好地对其进行可视化:
sed -E 's/[^,]+[^0-9]([0-9][0-9]+)[^,]+/\1/g' data.csv
输出:
rvb@ubuntu:~$ sed -E 's/[^,]+[^0-9]([0-9][0-9]+)[^,]+/\1/g' data.csv
header1, header2, certain Titel in Header, certain Titel2 in Header, certain Titel3 in Header
,,7846641,8974341,823241
,,7846642,8974342,823242
,,7846643,8974343,823243
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.