Sed

替換第一個單詞保持文件對齊

  • May 15, 2020

我正在嘗試編寫一個 Shell 腳本來編輯輸入文件。輸入文件中的資料結構如下:

1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000            : print time
0.1             : time step

對齊是用第一行強調的空格進行的。我目前正在使用sed替換參數(每行的第一個“單詞”)。

如果不弄亂標籤的對齊方式,我找不到一種方法。我願意接受任何建議,我並不是特別想用sed. 例如,可以通過使用選項卡來更改輸入文件的結構。

這是我希望腳本執行的範例:

input file
----------
1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000            : print time
0.1             : time step
running the script
------------------
$ script --final-time=100
input file after running the script
-----------------------------------
100␣␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000            : print time
0.1             : time step

替換字元串的長度事先不知道。它不是固定的,最多可以是 6 個字元。

改用awk並使用 . 將欄位格式化為正確的寬度sprintf()。這很可能比使用sed.

$ cat file
1000            : final time
1000            : print time
0.1             : time step
$ awk -F ':' -v sect=' final time' -v val='100' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
100             : final time
1000            : print time
0.1             : time step

這處理由 -:分隔的欄位組成的輸入行。當第二個欄位對應於命令行上給sect變數的字元串時awk,第一個欄位被val命令行上給定的值替換。

這裡使用的方式sprintf(),格式字元串為%-16s,確保您在:.

使用相同的命令設置“時間步長”只需要為sectand插入其他值val

$ awk -F ':' -v sect=' time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
1000            : final time
1000            : print time
0.12121212      : time step

sect需要值開頭的空格來說明 . 之後的數據中的空格:。你也可以做

$ awk -F ':' -v sect='time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == " " sect { $1 = sprintf("%-16s", val) }; 1' file
1000            : final time
1000            : print time
0.12121212      : time step

(我將值中的空間移到了sect針對第二列值的測試中。)


腳本建議(使用輸入文件的靜態文件路徑,只輸出修改後的數據):

#!/bin/sh

filepath=some/file/path

if [ "$#" -ne 2 ]; then
   echo expecting two arguments >&2
   exit 1
fi

case $1 in
   --final-time) sect='final time' ;;
   --print-time) sect='print time' ;;
   --time-step)  sect='time step'  ;;
   *)
       printf 'Unknown argument: %s\n' "$1" >&2
       exit 1
esac

val=$2

awk -F ':' -v sect="$sect" -v val="$val" '
   BEGIN { OFS=FS }
   $2 == " " sect { $1 = sprintf("%-16s", val) }; 1' "$filepath"

引用自:https://unix.stackexchange.com/questions/586852