Bash脚本:保持一行本地文件与远程文件同步

我search了高低,但似乎无法find解决这个问题(也许它不存在?)。 这是我的问题:

我的本地机器上有一个名为myFile.txt的文件。 在远程计算机上有一个相同名称的文件(myFile.txt)。 两个文件结构都是这样的:

<tag1>November 22, 2012<tag1> <tag2>version5.8<tag2> <tag3>ASDFA23RASDF29ASDJ29DJ2<tag3> 

两个文件都有完全相同的布局。 我需要编写一个脚本,使两个文件(本地和远程)的<tag3>之间的string保持同步。 我需要从远程服务器上的<tag3>获取string,并将其与本地计算机上的相同string进行比较。 如果有区别,我需要改变我的本地string,以反映远程的。

到目前为止,我已经尝试过了:我使用awk抓取了本地string,并将其分配给一个variables。 很简单。 我ssh'ed到远程服务器,并试图使用相同的方法来分配远程string到一个variables。 据我所知,这似乎是工作。 问题是variables不会返回到我的本地机器的值(如果这是有道理的)。 这是我试图做到这一点:

 #!/bin/bash fileName="myFile.txt" logon="myUserName@remoteServer.com" localString=$(awk -F "<tag3>" '{print $2}' $fileName) x=$(ssh $logon "remoteString=$(awk -F "<tag3>" '{print $2}' $fileName); echo $remoteString") echo "remote string = $x" if [ $localString == $x ]; then echo "The 2 auth keys are EQUAL!!!" else echo "The 2 auth keys are NOT equal!!!" fi 

我可以看到当我回显$ remoteString时分配的variables。 从我的理解,这是发生在远程服务器上,虽然我得到正确的string打印到控制台后面的“命令未find”。 下一行回显的“远程string=”。 所以$ x要么失去它的价值,要么永远不能正确分配。 我已经尝试改变这个行$ x分配了很多很多时间,但没有任何运气。

其他的想法:如果这是不可能的,我开始想,也许我需要做一个文件的SCP,把它带到我的服务器,进行比较,然后删除复制的领域。 我将需要更改副本的名称,然后将其移动到本地计算机,否则我将覆盖我的文件。 另外,不必制作安全副本似乎更有效率,因为这个脚本必须在许多机器上运行,并且该文件可能会比3行大得多。 我已经看过差异,但无法find一种方法来比较只有一行。

我对bash脚本相当陌生,所以请原谅我,如果我失去了一些明显的东西。 感谢您的任何帮助,因为它是不胜感激。

你可以沿着这些线使用一些东西:

 #!/bin/bash fileName="myFile.txt" logon="myUserName@remoteserver.com" sedcommand='/^<tag3>.*<tag3>$/{s/<tag3>\(.*\)<tag3>/\1/p;q}' localString=$( sed -n $sedcommand "$fileName" ) remoteString=$( ssh "$logon" "sed -n '$sedcommand' \"$fileName\"" ) if [[ $localString == $remoteString ]]; then echo "The 2 auth keys are EQUAL!!!" else echo "The 2 auth keys are NOT equal!!!" fi 

(这似乎比你的方法简单)。 sed命令查找以<tag3>开始并以<tag3>结尾的行的第一次出现,并移除标签以仅传送“auth密钥”。 不存在对不存在的文件的警惕,或者对标签不被查找。 这个细节留给读者。 但是脚本对于文件名中的空格是安全的,并且不使用两个嵌套的子壳体!

ssh命令存在一个转义问题 – 你应该在ssh参数中ssh $

然后,我刚刚替换了remoteString=$(awk ....); echo $remoteString remoteString=$(awk ....); echo $remoteStringawk .... 如果不是这样,那么会出现一些导致字符串不匹配的空白行的问题 – 并且存储命令的输出仅仅是为了echo它,这似乎是无用的。

 #!/bin/bash fileName="myFile.txt" logon="myUserName@remoteserver.com" localString=$(awk -F "<tag3>" '{print $2}' $fileName) x=$(ssh $logon "awk -F '<tag3>' '{print \$2}' $fileName") echo "remote string = $x" if [ "$localString" == "$x" ]; then echo "The 2 auth keys are EQUAL!!!" else echo "The 2 auth keys are NOT equal!!!" fi 

尝试改变这一行:

 x=$(ssh $logon "remoteString=$(awk -F "<tag3>" '{print $2}' $fileName); echo $remoteString") 

 x=$(ssh $logon "remoteString=$(awk -F '<tag3>' '{print $2}' $fileName); echo $remoteString") 

即:将"<tag3>"更改为'<tag3>'

我有一种感觉,你目前使用的双引号实际上打破了你的SSH命令的预期用途。


作为一个方面说明:当你单独[条件测试的情况下,总是包裹你的变量在双引号:

 if [ $localString == $x ]; then 

会更安全,因为:

 if [ "$localString" == "$x" ]; then 

要么

 # this also works, but less portable if [[ $localString == $x ]]; then 

原因是,如果任一变量的值为空字符串(假设在这种情况下x是空的),bash会看到类似这样的内容: if [ ASDFA23RASDF29ASDJ29DJ2 == ]; then if [ ASDFA23RASDF29ASDJ29DJ2 == ]; then