用Shell脚本替换文本文件中的占位符,可能用sed或awk

lvmkulzt  于 2023-05-18  发布在  Shell
关注(0)|答案(5)|浏览(267)

我有一个输入文件,每行总是有3个值,用“…”分隔

1,2,3
4,5,6
....

每一行都应该粘贴在一个模板文件中,每一行都要有一个自己的文件,用连续数字写,比如01.txt 02.txt
template.txt

<wpt col="value1" cal="value2"><name>value3</name></wpt>

我如何才能做到这一点?在这台机器上,我只能使用shell脚本。没有Python或其他语言可用,也不能安装

qnakjoqk

qnakjoqk1#

使用printf
c=0
while IFS=, read -r c1 c2 c3; do
    ((c++))
    printf -v count '%.2d' $c
    printf '<wpt col="value%d" cal="value%d"><name>value%d</name></wpt>\n' \
        $c1 $c2 $c3 > "$count.txt"
done < file
使用shell模板文件,包含变量和envsubst

man envsubst
envsubst -替换shell格式字符串中的环境变量

cat template.tpl 
<wpt col="value$c1" cal="value$c2"> <name>value$c3</name></wpt>
c=0
while IFS=, read -r c1 c2 c3; do
    ((c++))
    printf -v count '%.2d' $c
    export c1=$c1 c2=$c2 c3=$c3
    envsubst < template.tpl > "$count.txt"
done < file

然后

ls -1 *.txt
nzk0hqpo

nzk0hqpo2#

一种使用awk的方法,使用sprintf化输出文件名中的数字。
请记住,这将覆盖具有相同名称的现有文件。

% awk -F ',' '{
    nr=sprintf("%02d", NR)
    print "<wpt col=\""$1"\" cal=\""$2"\"><name>"$3"</name></wpt>" > (nr".txt"); close(nr".txt")
  }' file

或,包括阅读 template.txt 文件

% awk -F ',' 'NR==FNR{tem=$0; next} 
    {nr=sprintf("%02d", FNR)
     sub(/col=.* /, "col=\""$1"\" ", tem)
     sub(/cal=.*\"><name/, "cal=\""$2"\"><name", tem)
     sub(/<name>.*<\/name>/, "<name>"$3"</name>", tem)
     print tem > (nr".txt"); close(nr".txt")}' template.txt file

结果

% cat 01.txt
<wpt col="1" cal="2"><name>3</name></wpt>
% cat 02.txt
<wpt col="4" cal="5"><name>6</name></wpt>
wj8zmpe1

wj8zmpe13#

这可能对你有用(GNU sed和split):

sed -E 's/(.*),(.*),(.*)/<wpt col="\1" cal="\2"><name>\3<\/name><\/wpt>/' file |
split -l1 --add=.txt --numeric=01 - ''

将文件的每一行操作为所需的格式,然后将每一行拆分为一个单独的文件。

dxxyhpgq

dxxyhpgq4#

通常情况下,我会先等着看你解决问题的尝试,这样我就可以帮助你的代码,但既然你已经有了答案...

$ cat tst.awk
BEGIN { FS="," }
NR==FNR {
    tmplt = $0 ORS
    gsub(/value[0-9]+/,"%s",tmplt)
    next
}
{
    out = sprintf("%02d.txt", FNR)
    printf tmplt, $1, $2, $3 > out
    close(out)
}
$ awk -f tst.awk template.txt file
$ head 0*.txt
==> 01.txt <==
<wpt col="1" cal="2"><name>3</name></wpt>

==> 02.txt <==
<wpt col="4" cal="5"><name>6</name></wpt>

上面的内容可以使用任何awk,并且假设模板行不包含任何printf字符,例如%svalue[0-9]+,只在所需的上下文中匹配。

t40tm48m

t40tm48m5#

别浪费时间一个一个做。只需使用awk大规模生成printf语句,然后使用轻量级shell一次性执行所有语句(额外的好处是在awk中不必不间断地关闭文件):

gfind . -type f -print0 | xargs -0 grm -v 
ls -nAlFrt
removed './01.txt'
removed './02.txt'
removed './03.txt'
total 0
echo $'1,2,3\n4,5,6\n7,8,9' | 

mawk '$!NF=sprintf("printf \47%%s\47 \47<wpt col=\"%s\" cal=\"%s\"><name" \
           ">%s</name></wpt>\47 > \47%.2d.txt\47 ;",$1,$2,$3,NR)' FS=',' | 

gtee >( gpaste | gcat -n >&2; cat ) | dash
ls -nAlFrt
total 12
-rw-r--r--  1 501  20  41 May  8 08:29 01.txt
-rw-r--r--  1 501  20  41 May  8 08:29 02.txt
-rw-r--r--  1 501  20  41 May  8 08:29 03.txt
for __ in *.txt; do 

   gcat  -n "$__"
   echo "\n\t$__\n"

done

相关问题