我有一个文件名为file.csv的文件,内容为
adult,REZ
man,BRB
women,SYO
animal,HIJ
和既不是目录也不是文件的行
file.csv BRB1 REZ3 SYO2
我想做的是用这一行的单词改变文件的内容,然后得到这个单词的第n个字母,这些单词末尾的数字是大写的然后输出应该是
umo
我知道我可以通过
for i in "${@:2}"
do
words+=$(echo "$i ")
done
,然后输出
REZ3 BRB1 SYO2
使用awk
:
传递值字符串作为awk变量,然后将它们拆分为数组a
。对于file.csv中的每条记录,迭代该数组,如果当前记录的第二个字段与当前数组值的前三个字符匹配,则从当前记录的第一个字段中删除目标字符,并将其附加到一个变量。打印聚合变量的值。
awk -v arr="BRB1 REZ3 SYO2" -F, 'BEGIN{split(arr,a," ")} {for (v in a) { if ($2 == substr(a[v],0,3)) {n=substr(a[v],length(a[v]),1); w=w""substr($1,n,1) }}} END{print w}' file.csv
umo
您也可以将其放入脚本中:
#!/bin/bash
words="${2}"
src_file="${1}"
awk -v arr="$words" -F, 'BEGIN{split(arr,a," ")}
{for (v in a) {
if ($2 == substr(a[v],0,3)) {
n=substr(a[v],length(a[v]),1);
w=w""substr($1,n,1);
}
}
} END{print w}' "$src_file"
脚本执行:
./script file.csv "BRB1 REZ3 SYO2"
umo
这是使用sed的一种方法。从命令参数创建模式字符串,并使用sed转换行。
#!/bin/bash
file="$1"
pat='s/^/ /;Te;'
for i in ${@:2}; do
pat+=$(echo $i | sed 's#^([^0-9]*)([0-9]*)$#s/.\{2\}\(.\).*,1$/\1/;#')
done
pat+='Te;H;:e;${x;s/n//g;p}'
eval "sed -n '$pat' $file"
试试下面的代码:
#!/bin/bash
declare -A idx_dic
filename="$1"
pattern_string=""
for i in "${@:2}";
do
pattern_words=$(echo "$i" | grep -oE '[A-Z]+')
index=$(echo "$i" | grep -oE '[0-9]+')
pattern_string+=$(echo "$pattern_words|")
idx_dic["$pattern_words"]="$index"
done
pattern_string=${pattern_string%|*}
while IFS= read -r line
do
line_pattern=$(echo $line | grep -oE $pattern_string)
[[ -n $line_pattern ]] && line_index="${idx_dic[$line_pattern]}" && echo $line | awk -v i="$line_index" '{split($0, chars, ""); printf("%s", chars[i]);}'
done < $filename
- 首先查找大写单词模式并捕获对应的索引
- 然后构建与
|
连接的孔模式字串。最后,根据模式串遍历每一行,通过索引找到对应的字母。
执行script.sh
:
bash script.sh file.csv BRB1 REZ3 SYO2