使用 sed 抓取某些文本并将排序+输入回文件中



我想请求一些帮助。

我目前正在创建一个脚本,该脚本将有一个充满格式化文本的设置文件作为基础,然后根据用户输入从该文本文件输入和删除。我会把它放到bash脚本中。

我已经想出了如何使用以下命令从文件中获取我需要的文本:

sed -n '/5.1.1"/,/|}/p' textfile.txt

5.1.1 是我的服务器的机架位置,我正在抓取文件的文本,直到它找到 |}。

这将输出如下内容:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

依此类推,直到 5.1.15。

sed 只是选择我需要更改的文本。

我思考如何做到这一点的方式是获取我用 sed 抓取的文本,插入我需要的行,然后根据第二列中的数字对其进行排序,然后将更改后的文本重新插入到同一位置的文件中,但是我不知道如何实现这一点。

我将输入的行将采用与其他行相同的格式,然后我将在其下方显示一个|-。

谢谢

编辑 1:

因此,所需的输出将是:

我有第 16 行:服务器名称;我想在机架 5.1.1 中输入到这个文件中。

从上面取基础的最终结果将是:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|16: servername;
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

编辑 2:

我想我应该包括我写的脚本来进行格式化。它不完整且非常卡顿,但除了 $location 变量的 if 之外,它还起到了作用。我需要为此重新设计正则表达式。

#! /bin/bash

function serverread {
#Enter the location
function locationread { 
echo 'Enter the location of the server in the data center in format (x.x.x) ex. 5.1.15'
read location
if [[ "$location" =~ [0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2} ]]
then
echo "Success"
else
echo "You have entered an incorrect format for the rack, please try again."
locationread
exit
fi
}
locationread
echo Please enter the rack space at which the server was placed
read rp
if (( $rp < 1 || $rp > 42));
then
echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
read rp
else
{
echo You entered: $rp as the server placement in the rack.
}
fi
#Enter the server name
echo Now please enter the server name "(Use ~ around the name if it is disconnected/unplugged)":
read name
if [[ $name == ~* ]] && [[ $name == *~ ]];
then
echo "You entered: $name as the server name and it is currently disconnected in some way."
else
echo "You entered: $name as the server name."
fi
#Enter the physical height of the server
echo Now please enter the size in height of the server:
function readsize {
read size
if [ $size -eq $size 2>/dev/null ]
then
if (( $size < 1 || $size > 42));
then
echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
readsize
else
echo "You entered: $size as the physical height of the server"
fi
fi
}
readsize
#if (( $size == 1))
#
#  else
#                echo "$size is not an integer"
#        fi
#       
#if (( $size < 1 || $size > 42));
#then
#        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
#        read size
#else
#        echo "You entered: $size as the physical height of the server"
#fi
if (( $size == 1));
then
echo Currently this is the line that will be entered: $rp": "$name";"
else
echo Currently this is the line that will be entered: $rp": "$name" ["$size"U];"
fi
echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2
if (( $matrix == "yes" ));
then
if (( $matrix2 == "yes" ));
then
serverread
else
echo This is complete
exit
fi
else
echo Please run this command again
exit
fi
}
serverread

编辑3:

这就是我将最后一个函数更改为适合脚本的内容:

set finale="($rp": "$name" ["$size"U];""
echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2
if (( $matrix == "yes" ));
then
{
# all text before 5.1.1
sed -n '/'"$location"'"/q;p;' racktext.txt;
# parse text in this section
sed -n '/'"$location"'"/,/|}/p' racktext.txt | input.sh
# all text below this section
sed -n '/'"$location"'"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' racktext.txt
# use sponge to overwrite the file in a pipeline
} | sponge racktext.txt
if (( $matrix2 == "yes" ));
then
serverread
else
echo This is complete
exit
fi
else
echo Please run this command again
exit
fi
}
serverread

这就是我将如何执行您在单独文件中向我展示的脚本:

#! /bin/bash
export $(cat rackformat | grep -v ^# | xargs)
echo $finale
while IFS= read -r l; do 
if [[ "$l" =~ description ]]; then            
msg="$l"$'n';                 
elif [[ "$l" =~ "}" ]]; then                    
{ 
echo -n "$msg" | grep -v '|-'; 
echo "|$finale"; 
} | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
echo "$l"; 
echo '|-'; 
done | head -n-1; 
echo '|}'; 
else 
msg+="$l"$'n'; 
fi; 
done

编辑4:

我没有包括上述部分,因为我认为它不相关,但我可能应该包括它,这是我的错。 这是输入之前的文本文件:

{| class="wikitable"
|
{| class="wikitable"
|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername~;
|-
|39: servername;
|-
|41: servername;
|}
|
{| class="wikitable"

这是当前脚本的输出:

{| class="wikitable"
|
{| class="wikitable"
||2.: test [2U];
|-
|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername~;
|-
|39: servername;
|-
|41: servername;
|}
|
{| class="wikitable"

以下是当前脚本的全部内容:

#! /bin/bash

function serverread {
#Enter the location
function locationread {
echo 'Enter the location of the server in the data center in format (x.x.x) ex. 5.1.15'
read location
if [[ "$location" =~ [0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2} ]]
then
echo "Success"
else
echo "You have entered an incorrect format for the rack, please try again."
locationread
exit
fi
}
locationread
function parser {
while IFS= read -r l; do 
if [[ "$l" =~ description ]]; then            
msg="$l"$'n';                 
elif [[ "$l" =~ "}" ]]; then                    
{ 
echo -n "$msg" | grep -v '|-'; 
echo "|$finale"; 
} | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
echo "$l"; 
echo '|-'; 
done | head -n-1; 
echo '|}'; 
else 
msg+="$l"$'n'; 
fi; 
done
}
echo Please enter the rack space at which the server was placed
read rp
if (( $rp < 1 || $rp > 42));
then
echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
read rp
else
{
echo You entered: $rp as the server placement in the rack.
}
fi
#Enter the server name
echo Now please enter the server name "(Use ~ around the name if it is disconnected/unplugged)":
read name
if [[ $name == ~* ]] && [[ $name == *~ ]];
then
echo "You entered: $name as the server name and it is currently disconnected in some way."
else
echo "You entered: $name as the server name."
fi
#Enter the physical height of the server
echo Now please enter the size in height of the server:
function readsize {
read size
if [ $size -eq $size 2>/dev/null ]
then
if (( $size < 1 || $size > 42));
then
echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
readsize
else
echo "You entered: $size as the physical height of the server"
fi
fi
}
readsize
#if (( $size == 1))
#
#  else
#                echo "$size is not an integer"
#        fi
#       
#if (( $size < 1 || $size > 42));
#then
#        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
#        read size
#else
#        echo "You entered: $size as the physical height of the server"
#fi
if (( $size == 1));
then
echo Currently this is the line that will be entered: $rp": "$name";"
else
echo Currently this is the line that will be entered: $rp": "$name" ["$size"U];"
fi
echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2
finale=$rp": "$name" ["$size"U];"
echo $finale
if (( $matrix == "yes" ));
then
function b {
# all text before 5.1.1
sed -n '/'"$location"'"/q;p;' racktext.txt;
# parse text in this section
sed -n '/'"$location"'"/,/|}/p' racktext.txt | parser
# all text below this section
sed -n '/'"$location"'"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' racktext.txt
# use sponge to overwrite the file in a pipeline
}
b | sponge racktext.txt
echo $
if (( $matrix2 == "yes" ));
then
serverread
else
echo This is complete
fi
else
echo Please run this command again
exit
fi
}
serverread

以下script.sh适用于您提供的在 stdin 上传递的示例:

#!/bin/bash
while IFS= read -r l; do 
if [[ "$l" =~ description ]]; then 
msg="$l"$'n'; 
elif [[ "$l" =~ "}" ]]; then 
{ 
echo -n "$msg" | grep -v '|-'; 
echo '|16: servername;'; 
} | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
echo "$l"; 
echo '|-'; 
done | head -n-1; 
echo '|}'; 
else 
msg+="$l"$'n'; 
fi; 
done

对于以下输入:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

它输出以下内容:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|16: servername;
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

由于您没有提供此文件格式的任何描述或其他示例,因此我假设:

  • |-行可以忽略和剥离,永远不会改变(起初我以为那些是空的抹布,但后来它们在 15 到 16 到 17 之间,所以不是(
  • 这些部分以说明开头,以|}结尾

要将其插入回脚本,您可以:

{ 
# all text before 5.1.1
sed -n '/5.1.1"/q;p;' textfile.txt;
# parse text in this section
sed -n '/5.1.1"/,/|}/p' textfile.txt | script.sh
# all text below this section
sed -n '/5.1.1"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' textfile.txt
# use sponge to overwrite the file in a pipeline
} | sponge textfile.txt

最新更新