[英]Bash script to manipulate two decimal numbers in a line
我正在处理的两行数据如下所示。
18 xy Pqr -3879.65 xp9 a-kxp Kap 97868.08 P8A jrh-uyjf iu-re
A4-18 usU Aqr 974.59 xpab9 Tb7k-p ptx 1533.93 K-doe Uap-qe1
主要特征:
我想翻转第一个数字的符号(正到负,反之亦然)并删除第二个数字。
由于 bash 技能有限,我用蛮力方法编写了以下脚本。 看起来好不优雅! 感谢论坛成员可能提供的任何指示以使其更好。
#replace whitespaces with "_" for easy 'sed'-ing
a=`echo "$this_line" | sed -e "s/ /_/g"`
#get head part with first decimal number
b=`echo $a | grep -Po '^.*?[-]?[0-9]+[\.][0-9]+'`
#pick the decimal number from the head part
c=`echo $b | grep -Po '[-]?[0-9]+[\.][0-9]+'`
#flip the sign of the decimal number from the head part
d=`echo -1 \* $c | bc -l`
#delete decimail number from the head part
e=`echo "$b" | sed -e "s/$c$//"`
#put back head part with the decimal number sign flipped
f=`echo $e$d`
#get tail part with second decimal number
g=`echo "$a" | sed -e "s/^$b//"`
#pick the decimal number from the tail part
h=`echo $g | grep -Po '^.*?[-]?[0-9]+[\.][0-9]+'`
#delete decimail number from the tail part
i=`echo "$g" | sed -e "s/^$h//"`
#join back without second decimal number and first decimal sign flipped
j=`echo $f" "$i`
#replace back "_" by whitespace
modified_line=`echo "$j" | sed -e "s/_/ /g"`
怎么样的东西
awk '
{
flipped=0
for (i=1; i< NF; i++) {
if ($i ~ /-*[0-9]+\.[0-9]+/) {
$i = (!flipped++) ? -$i : "";
}
}
print
}
'
产生
18 xy Pqr 3879.65 xp9 a-kxp Kap P8A jrh-uyjf iu-re
A4-18 usU Aqr -974.59 xpab9 Tb7k-p ptx K-doe Uap-qe1
在处理浮点数时,awk 是一个更好的工具,因为 Bash 没有浮点类型:
awk '{ printf ("%s %s %s %f %s %s %s %s %s\n", $1, $2, $3, -$4, $5, $6, $7, $9, $10) }' input_file
str="18 xy Pqr -3879.65 xp9 a-kxp Kap 97868.08 P8A jrh-uyjf iu-re"
echo "$str" \
| grep -Eo -- '-?[0-9]*\.[0-9]+' \
| head -n 1 \
| awk '{print ($1 * -1)}'
grep -Eo -- '-?[0-9]*\\.[0-9]+''
将查找任何以可选的连字符开头的字符串,后跟数字,然后是句点,然后是数字head -n 1
然后将只从 grep 中检索第一个结果awk '{print ($1 *- 1)}
然后将打印第一个数字乘以-1
(从而翻转符号)echo "$str" | grep -Eo -- '-?[0-9]*\.[0-9]+' | head -n 1 | awk '{print ($1 * -1)}'
使用 awk 和变量替换的更简单、更易读的解决方案
#get the string
string="A4-18 usU Aqr 974.59 xpab9 Tb7k-p ptx 1533.93 K-doe Uap-qe1"
#get the first number
firstNumber=$(echo $string | awk '{print $4}')
#get the second number
secondNumber=$(echo $string | awk '{print $8}')
#calculate absolute value
absoluteValue=${firstNumber#-}
#replace string
echo $string | sed s/$firstNumber/$absoluteValue/ | sed s/$secondNumber//
#!/bin/bash
msg="18 xy Pqr K -261.90 xp9 P a-kxp 7873.57 Kap P8A jrh-uyjf"
printf '%s\\n' "$msg"
#为了保留空格,用“_”替换它们
a= echo "$msg" | sed -e "s/ /_/g"
echo "$msg" | sed -e "s/ /_/g"
#显示字符串以显示断点
b= echo $a | sed -n "s/\\(^.*\\.[0-9].*_\\)\\([0-9]*\\.[0-9][0-9]\\)\\(.*$\\)/\\1|\\2|\\3/p"
echo $a | sed -n "s/\\(^.*\\.[0-9].*_\\)\\([0-9]*\\.[0-9][0-9]\\)\\(.*$\\)/\\1|\\2|\\3/p"
回声 $b
#删除第二个十进制数
b= echo $a | sed -n "s/\\(^.*\\.[0-9].*_\\)\\([0-9]*\\.[0-9][0-9]\\)\\(.*$\\)/\\1 \\3/p"
echo $a | sed -n "s/\\(^.*\\.[0-9].*_\\)\\([0-9]*\\.[0-9][0-9]\\)\\(.*$\\)/\\1 \\3/p"
#echo $b
#选择剩余字符串中存在的唯一十进制数
c= echo $b | grep -Po '[-]?[0-9]+\\.[0-9]+'
echo $b | grep -Po '[-]?[0-9]+\\.[0-9]+'
#更改十进制数的符号
d= echo -1 \\* $c | bc -l
echo -1 \\* $c | bc -l
#将十进制数替换回带有新符号的字符串
e= echo ${b/$c/$d}
#用空格替换回“_”
modified_line= echo "$e" | sed -e "s/_/ /g"
echo "$e" | sed -e "s/_/ /g"
printf '%s\\n' "$modified_line"
退出 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.