[英]How to replace a specific line in a file with a string variable using the line number bash script?
[英]How do I replace a specific number in a text file using a bash script?
晚上好 - 我非常堅持看起來應該是一個簡單的 sed 命令。 我有一個格式如下的文本文件 (init.input):
任何幫助,將不勝感激!
100 50 1
100 50 1
2 !The number of additional poutlet condition
45,1,1 762.143895,814.862101,0.999395
46,1,1 762.143895,814.862101,0.999395
之前在 bash 腳本中我定義了變量 cfjlines、var1、var2、var3。 在此示例中,cfjlines 指定該注釋行之后的行數,並且等於該行開頭的整數。
如果例如 var1=123.0, var2=456.0, var3=789.0,
我想要一個 bash 腳本函數來替換該文件最后 (cfjlines) 行的最后三個數字,如下所示:
100 50 1
100 50 1
2 !The number of additional poutlet condition
45,1,1 123.0,456.0,789.0
46,1,1 123.0,456.0,789.0
此示例中顯示的所有數字在以后的文件中都會更改,但位置很重要。 我嘗試將值分配給數組然后讀取失敗:```
# Extract the line containing the integer value from the input file
line=$(grep "!The number of additional poutlet condition" init.input)
# Extract the integer value from the line
cfjlines=$(cut -d' ' -f2 <<< "$line")
declare -a numbers
# Extract the last two lines of the file
last_lines=$(tail -n $cfjlines init.input)
# Delete last rows of init.input
head -n -$cfjlines init.input > temp.txt ; mv temp.txt init.input
# Loop through the lines of the last lines
while read -r line; do
# Replace spaces with commas in the line
modified_line=$(echo "$line" | tr ' ' ',')
# Append the modified line to the end of the original file
echo "$modified_line" >> init.input
done <<< "$last_lines"
# Set the IFS (internal field separator) to a comma
IFS=','
mapfile -t array < <(tail -n 1 init.input)
# Iterate over the elements in the array
for element in "${array[@]}"; do
# Split the element into fields using the IFS
read -ra fields <<< "$element"
# Replace the last three fields with var1, var2, and var3
fields[-3]="var1"
fields[-2]="var2"
fields[-1]="var3"
# Join the fields back together using the IFS and print the result
printf "%s\n" "${fields[*]}"
done
```
最后一部分給我一個錯誤,指出字段索引是一個錯誤的數組下標,但我認為那是因為我沒有正確地將最后一行的六個值放入六個數組元素中。
再次感謝您的幫助。 謝謝!
正如許多其他人可能會建議您的那樣,bash 不是進行內容操作的非常有效的工具。 所以在下面,我提供了一個基於awk的解決方案。
您的問題似乎表明前 3 行是靜態的,因此按原樣傳遞。
您的問題還暗示所有剩余的數據行都將第二個分組修改為相同的 3 個指定值。 您可以將這些值作為單獨的值傳遞(根據以下腳本的命令行位置),或者您可以將它們作為單個預格式化的字符串傳遞,如果不依賴於這些行的內容。
如果您需要基於行的值,上下文驅動的,基於每行上的值,那么您需要從為“數據”數組進行拆分的行中刪除注釋前綴,並評估/操作這些值在以下 printf 語句之前生成適當的替代品之前。
#!/bin/sh
if [ $# -eq 3 ]
then
VAR1=$1
VAR2=$2
VAR3=$3
else
VAR1=123.0
VAR2=456.0
VAR3=789.0
fi
echo "\
100 50 1
100 50 1
2 !The number of additional poutlet condition
45,1,1 762.143895,814.862101,0.999395
46,1,1 762.143895,814.862101,0.999395" |
awk -v var1="${VAR1}" -v var2="${VAR2}" -v var3="${VAR3}" '{
if( NR < 4 ){
### do not modify first 3 lines
print $0 ;
}else{
### split line into 2 groupings
split( $0, raw ) ;
### IF ncessary, split second grouping into distinct array values
#split( raw[2], data, "," ) ;
#for( i=1 ; i <= 3 ; i++ ){
# printf("\t data[%s] = %s\n", i, data[i] ) | "cat >&2 " ;
#} ;
### pass thru first grouping unmodified
printf("%s ", raw[1] ) ;
### replace 3 values on lines
printf("%s,%s,%s\n", var1, var2, var3 ) ;
} ;
}'
這是會話的執行日志:
ericthered@OasisMega1:/WORKS$ script.sh 999 777 333
100 50 1
100 50 1
2 !The number of additional poutlet condition
45,1,1 999,777,333
46,1,1 999,777,333
ericthered@OasisMega1:/WORKS$
或使用您提供的默認值,
ericthered@OasisMega1:/WORKS$ script.sh
100 50 1
100 50 1
2 !The number of additional poutlet condition
45,1,1 123.0,456.0,789.0
46,1,1 123.0,456.0,789.0
ericthered@OasisMega1:/WORKS$
根據您給定的輸入,這就是我要做的。
#!/usr/bin/env bash
start=0
var1=123.0
var2=456.0
var3=789.0
last_fields=3
file=init.input
cfjlines=$(
grep -Po '(?<=\s)\d+(?=\s!The number of additional poutlet condition)' "$file"
)
while IFS= read -ru3 line; do
if ((start++ >= cfjlines)); then
IFS=' ' read -ra fields <<< "${line//,/ }"
fields[-1]="$var3"
fields[-2]="$var2"
fields[-3]="$var1"
temp=$(IFS=','; printf '%s\n' "${fields[*]:last_fields}")
temp1="${fields[*]::last_fields}"
printf '%s\n' "${temp1// /,} $temp"
else
printf '%s\n' "$line"
fi
done 3< "$file"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.