我有一个文本文件,我正在试图修改。的形式有行的输入文件。
(y+1/4,-x+1/2,z+3/4)并试图把它改成
0 1 0 -1 0 0 0 0 1 1 / 4 1 / 2 3 / 4我现在可以讲到这一点
0 1 0 1/4 -1 0 0 1/2 0 0 1 3/4使用
#!bin/bash
filename="227.dat"
sed -i 's/(/ /g' $filename
sed -i 's/)//g' $filename
sed -i 's/,/ /g' $filename
sed -i 's/-x/-1 0 0/g' $filename
sed -i 's/x/ 1 0 0/g' $filename
sed -i 's/-y/ 0 -1 0/g' $filename
sed -i 's/y/ 0 1 0/g' $filename
sed -i 's/-z/ 0 0 -1/g' $filename
sed -i 's/z/ 0 0 1/g' $filename
sed -i '/+/! s/$/ 0 \/ 1 0 \/ 1 0 \/ 1/' $filename
while ((i++)); read -r line; do
if [[ $line == *[+]* ]]
then
sed -i 's/+/ /g' $filename
echo $i
fi
done < "$filename"echo $i的原因是看到它正确地给出了行号,我想也许我可以将它用于这些特定行上的命令。我正在进行这种转换,因为我们在创建晶体结构时所用的代码需要在末尾使用分数的向量表示法,而不是x、y、z表示法。我已经知道这不是“最漂亮”或最简单的解决方案,但我对所有这些都非常陌生,这也是迄今为止我能够拼凑起来的东西。有什么建议吗?
发布于 2017-11-10 01:48:05
#!/usr/bin/env bash
filename="227.dat"
re='[(]y[+]([[:digit:]/]+),-x[+]([[:digit:]/]+),z[+]([[:digit:]/]+)[)]';
while IFS= read -r line; do
if [[ $line =~ $re ]]; then
printf '\t%s' \
0 1 0 \
-1 0 0 \
0 0 1 \
"${BASH_REMATCH[1]}" \
"${BASH_REMATCH[2]}" \
"${BASH_REMATCH[3]}";
printf '\n';
else
echo "ERROR: $line does not match $re" 1>&2;
fi;
done <"$filename"您的输入...given返回:
0 1 0 -1 0 0 0 0 1 1/4 1/2 3/4据我所知,...which是正确的。
一种更为复杂的方法,即进行毫无根据的推断(考虑到问题本身缺乏细节和范例),可能如下所示:
#!/usr/bin/env bash
while IFS='(),' read -a pieces; do
declare -A vars=( [x]=1 [y]=1 [z]=1 [x_sigil]='' [y_sigil]='' [z_sigil]='' )
for piece in "${pieces[@]}"; do
# 1 2 3 4
if [[ $piece =~ (-?)([xyz])([+]([[:digit:]/]+))? ]]; then
if [[ ${BASH_REMATCH[4]} ]]; then # only if there *are* digits
vars[${BASH_REMATCH[2]}]=${BASH_REMATCH[4]} # ...then store them.
fi
vars[${BASH_REMATCH[2]}_sigil]=${BASH_REMATCH[1]} # store - if applicable
fi
done
printf '\t%s' \
"0" "${vars[x_sigil]}1" 0 \
"${vars[y_sigil]}1" 0 0 \
0 0 "${vars[z_sigil]}1" \
"${vars[y]}" "${vars[x]}" "${vars[z]}"
printf '\n'
done考虑到在对此答复的评论中提供的示例输入,输出如下:
0 1 0 1 0 0 0 0 1 1 1 1
0 1 0 1 0 0 0 0 1 1 1 1
0 1 0 1 0 0 0 0 1 1 1 1
0 1 0 1 0 0 0 0 -1 3/4 1/4 1/2
0 1 0 -1 0 0 0 0 1 1/2 3/4 1/4
0 -1 0 1 0 0 0 0 1 1/4 1/2 3/4
0 -1 0 -1 0 0 0 0 -1 1 1 1
0 -1 0 -1 0 0 0 0 -1 1 1 1
0 -1 0 -1 0 0 0 0 -1 1 1 1
0 -1 0 -1 0 0 0 0 1 1/4 3/4 1/2
0 -1 0 1 0 0 0 0 -1 1/2 1/4 3/4
0 1 0 -1 0 0 0 0 -1 3/4 1/2 1/4
0 -1 0 -1 0 0 0 0 1 1/4 3/4 1/2
0 -1 0 -1 0 0 0 0 1 1/4 3/4 1/2
0 -1 0 -1 0 0 0 0 1 1/4 3/4 1/2
0 -1 0 -1 0 0 0 0 -1 1 1 1
0 -1 0 1 0 0 0 0 1 1/4 1/2 3/4
0 1 0 -1 0 0 0 0 1 1/2 3/4 1/4
0 1 0 1 0 0 0 0 -1 3/4 1/4 1/2
0 1 0 1 0 0 0 0 -1 3/4 1/4 1/2
0 1 0 1 0 0 0 0 -1 3/4 1/4 1/2
0 1 0 1 0 0 0 0 1 1 1 1
0 1 0 -1 0 0 0 0 -1 3/4 1/2 1/4
0 -1 0 1 0 0 0 0 -1 1/2 1/4 3/4
0 -1 0 1 0 0 0 0 -1 1/2 1/4 3/4
0 -1 0 1 0 0 0 0 -1 1/2 1/4 3/4
0 -1 0 1 0 0 0 0 -1 1/2 1/4 3/4
0 -1 0 1 0 0 0 0 1 1/4 1/2 3/4发布于 2017-11-10 02:42:25
下面是一种简化解析的方法。使用设置为所有可能的分隔符和字符的IFS将每一行读入数组:
while IFS=$'\(\)+,' read -ra line; do
for i in 1 3 5; do
case "${line[$i]}" in
x) printf "%s\t%s\t%s\t" 1 0 0 ;;
y) printf "%s\t%s\t%s\t" 0 1 0 ;;
z) printf "%s\t%s\t%s\t" 0 0 1 ;;
-x) printf "%s\t%s\t%s\t" -1 0 0 ;;
-y) printf "%s\t%s\t%s\t" 0 -1 0 ;;
-z) printf "%s\t%s\t%s\t" 0 0 -1 ;;
esac
done
for i in 2 4 6; do
printf "%s\t" "${line[$i]}"
done
echo
done < "$filename"https://stackoverflow.com/questions/47214248
复制相似问题