簡體   English   中英

用於在一行中操作兩個十進制數的 Bash 腳本

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM