本地文件和AU答案之间的代码版本控制

介绍

请注意,这是一个“分享知识”的自我回答的问题。

在我的系统上下载与源代码(脚本)链接的Ask Ubuntu答案需要“仅限bash”脚本。 然后使用diff命令比较两者。

关键是要发现我的代码是否已被更改并且AU答案需要更新,或者有人修改了我发布的AU答案,我需要将这些更改滚动到我的代码中。

websync脚本

 #!/bin/bash # NAME: websync # Must have the yad package. command -v yad >/dev/null 2>&1 || { echo >&2 \ "yad package required but it is not installed. Aborting."; \ exit 99; } RenumberListArr () { IFS='|' ListArrCnt=${#ListArr[@]} i=1 # First array element (0) is "false", followed by record number element (1) j=1 # All Record numbers count starting at 1 while [ $i -lt $ListArrCnt ] ; do ListArr[$i]=$j j=$(($j + 1)) i=$(($i + $RecArrCnt)) done } # RenumberListArr () ColSelect=0 ColRecNo=1 ColFileDate=2 ColFileName=3 ColStatus=4Address ColAnsDate=5 ColA_Votes=5 ColWebAddr=6 ColQ_Votes=7 ColTitle=8 NewFileDate=0 NewFileName=1 NewStatus=2 NewAnsDate=3 NewA_Votes=3 NewWebAddr=4 NewQ_Votes=5 NewTitle=6 LineOut="" HTMLtoText () { LineOut=$1 # Parm 1= Input line LineOut="${LineOut//&/&}" LineOut="${LineOut//</<}" LineOut="${LineOut//>/>}" LineOut="${LineOut//"/'"'}" LineOut="${LineOut//'/"'"}" LineOut="${LineOut//“/'"'}" LineOut="${LineOut//”/'"'}" } # HTMLtoText () Ampersand=$'\046' Equals="=================================================================================" Dashes="---------------------------------------------------------------------------------" AnswerID="" PercentFile="/tmp/websync-percent" # Temp file used for progress bar percentage UpdateEntry () { # PARM: 1=ONE display msgs, else file name for messages. if [[ $1 == "ONE" ]] ; then bDisplayMsgs=true MsgFileName="" # In case a single update follows all update else bDisplayMsgs=false MsgFileName="$1" fi local BarNo="2" # $RecArr[@] must be populated # Searches in order they are found in an answer SearchTitle=true FoundTitle=false SearchQ_Vote=true FoundQ_Vote=false SearchA_Vote=true FoundA_Vote=false FoundLine1=false FoundLine2=false FoundLine3=false EndOfFile=false AnswerWritten=false AnswerID=$(echo ${RecArr[$ColWebAddr]} | rev | cut -d# -f1 | rev) # Get file modified date in human readable format using STAT RecArr[$ColFileDate]=$(stat "${RecArr[$ColFileName]}" | \ grep "Modify:"| cut -f2 -d" ") HoldIFS="$IFS" IFS=$'\n' # make newlines the only separator AnswerSize=$(stat -c%s "/tmp/$AnswerID") # If answer size less < 1000 then wget failed. if [[ $AnswerSize -lt 1000 ]] ; then yad --error --center \ --text="wget failed to download answer from Stack Exchange." RecArr[$ColA_Status]="Answer < 1K" IFS="$HoldIFS" return 1 fi FirstThreeLines=() FirstThreeLines=( $(head -n10 ${RecArr[$ColFileName]}) ) AnswerLines=0 AllLinesSize=0 LastPercent=0 fPrintNextLine=false # Use this for tracing HTML and displaying Line echo $BarNo:0 > "$PercentFile" # Just in case last time temp file wasn't removed fEOFskip=false while IFS= read -r Line; do AnswerLines=$(( ++AnswerLines )) AllLinesSize=$(( $AllLinesSize+${#Line} )) if [[ $Line == *"$Ampersand""lt;/code$Ampersand""gt;"* ]] ; then # Answer contains  in text section, it's a fake End of Code tag. fEOFskip=true else fEOFskip=false fi # Convert HTML codes to normal characters HTMLtoText $Line Line="$LineOut" Percent=$(( $AllLinesSize * 100 / $AnswerSize )) if [[ "$Percent" -ne "$LastPercent" ]] ; then LastPercent=$Percent # Send percentage via working file to spawned process with yad progress bar echo $BarNo:$Percent > "$PercentFile" fi if [ $fPrintNextLine = true ] ; then echo "Line at start: $Line" fi # Parse Line:   if [ $SearchTitle = true ] ; then if [[ $Line == *"
"* ]] ; then SearchTitle=false ; fi continue fi if [ $SearchTitle = false ] && [ $FoundTitle = false ] ; then if [[ $Line == *"

" -f 3 <<< "$Line") Title=$(cut -d "<" -f 1 <<< "$Title") HTMLtoText $Title RecArr[$ColTitle]="$LineOut" fi continue fi if [ $SearchQ_Vote = true ] ; then if [[ $Line == *"
" -f 2 <<< "$Line") QuestionVotes=$(cut -d "<" -f 1 <<< "$QuestionVotes") RecArr[$ColQ_Votes]=$QuestionVotes fi continue fi # Parse lines: #
if [ $SearchA_Vote = true ] ; then if [[ $Line == *"
" -f 2 <<< "$Line") AnswerVotes=$(cut -d "<" -f 1 <<< "$AnswerVotes") RecArr[$ColA_Votes]=$AnswerVotes fi continue fi if [ $FoundLine1 = false ] ; then if [[ $Line == *"${FirstThreeLines[0]}"* ]] ; then # May have prefix FoundLine1=true # Create file with first line taken from "clean" bash array echo "${FirstThreeLines[0]}" > /tmp/websync-webfile fi continue fi if [ $FoundLine1 = true ] && [ $FoundLine2 = false ]; then # Empty lines aren't in our array so skip test if in web file if [[ $Line == "" ]] ; then echo "$Line" >> /tmp/websync-webfile # Append empty line continue fi if [[ $Line == "${FirstThreeLines[1]}" ]] ; then # Line 2 match exactly? FoundLine2=true echo "$Line" >> /tmp/websync-webfile # Append second line else # Line 2 doesn't match so force search to restart at line 1 FoundLine1=false fi continue fi if [ $FoundLine2 = true ] && [ $FoundLine3 = false ]; then # Empty lines aren't in our array so skip test if in web file if [[ $Line == "" ]] ; then echo "$Line" >> /tmp/websync-webfile # Append empty line continue fi if [[ $Line == "${FirstThreeLines[2]}" ]] ; then # Line 3 match exactly? FoundLine3=true echo "${FirstThreeLines[2]}" >> /tmp/websync-webfile # Append third line else # Line 3 doesn't match so force search to restart at line 1 FoundLine1=false FoundLine2=false fi continue fi # We are only here when first three code lines have matched up in Stack Exchange. if [ $EndOfFile = false ] ; then if [[ $Line == *""* ]] && [[ $fEOFskip == false ]] ; then EndOfFile=true else echo "$Line" >> /tmp/websync-webfile fi fi if [ $fPrintNextLine = true ] ; then echo "Line at end: $Line" fPrintNextLine=false elif [[ $Line == *"---- ENTER SEARCH STRING HERE ----"* ]] ; then fPrintNextLine=true fi done < "/tmp/$AnswerID" echo $BarNo:100 > "$PercentFile" # force spawned yad progress bar to close if [[ ! -f "${RecArr[$ColFileName]}" ]] ; then # File exists? yad --error --center --text "${RecArr[$ColFileName]} does not exist." RecArr[$ColStatus]="Bad File" elif [[ ! -s "${RecArr[$ColFileName]}" ]] ; then # File not empty? yad --error --center --text "${RecArr[$ColFileName]} is empty." RecArr[$ColStatus]="Empty File" fi if [ $FoundLine1 = true ] && [ $FoundLine2 = true ] && [ $FoundLine3 = true ]; then FileDiff="/tmp/websync-diff-"$(date +%s) if [[ "$MsgFileName" != "" ]] ; then echo $Equals >> $MsgFileName fi diff --unified=2 -w -b -B -I --suppress-blank-empty \ --ignore-tab-expansion --suppress-common-lines --ignore-all-space \ ${RecArr[$ColFileName]} /tmp/websync-webfile > $FileDiff # If file doesn't exist, errors in diff parameters # If file size =0 there were no differences if [[ -f $FileDiff ]] ; then if [[ -s $FileDiff ]] ; then if [[ $bDisplayMsgs == true ]] ; then # File not empty. gedit $FileDiff else cat $FileDiff >> $MsgFileName fi RecArr[$ColStatus]="Different" else if [[ $bDisplayMsgs == true ]] ; then yad --info --center --text \ "Code in ${RecArr[$ColFileName]} matches on Stack Exchange." else echo "Code in ${RecArr[$ColFileName]} matches on Stack Exchange." \ >> $MsgFileName echo $Dashes >> $MsgFileName fi RecArr[$ColStatus]="Matches" fi else yad --error --center --text "websync - Error in `diff` parameters." RecArr[$ColStatus]="Diff Parameter Error" fi else if [[ $bDisplayMsgs == true ]] ; then yad --error --center --text \ "First three lines of ${RecArr[$ColFileName]} not found on Stack Exchange." else echo $Equals >> $MsgFileName echo "First three lines of ${RecArr[$ColFileName]} not found on Stack Exchange." \ >> $MsgFileName echo $Dashes >> $MsgFileName fi RecArr[$ColStatus]="3 lines not found" fi IFS="$HoldIFS" # Remove Work files rm "/tmp/$AnswerID" rm /tmp/websync-webfile rm "$PercentFile" rm "$FileDiff" return 0 } # UpdateEntry () UpdateOne () { # $RecArr[@] must be populated # $1= ONE or $MsgFileName # $2= Bar 1 # Download stack exchange answer AnswerID=$(echo ${RecArr[$ColWebAddr]} | rev | cut -d# -f1 | rev) # Answer# for file name local BarNo="1" echo "$BarNo:10" > "$PercentFile" # Zero percent complete echo "$BarNo:#Downloading with wget." > "$PercentFile" wget -O- "${RecArr[$ColWebAddr]}" > "/tmp/$AnswerID" if [[ "$?" -ne 0 ]] # check return code for errors then # Sometimes a second attempt is required. Not sure why. wget -O- "${RecArr[$ColWebAddr]}" > "/tmp/$AnswerID" fi if [[ "$?" == 0 ]] # check return code for errors then echo "$BarNo:100" > "$PercentFile" echo "$BarNo:#Download completed." > "$PercentFile" else echo "$BarNo:100" > "$PercentFile" echo "$BarNo:#Download error." > "$PercentFile" echo "ERROR: $AnswerID" >> ~/websync.log return 1 fi UpdateEntry $1 ret=$? if [[ $ret != 0 ]] ; then # We weren't able to anayze SE answer -- too small return 1 fi ((TransCount++)) # Update count of changes # Update array entry let i=1 while [[ $i -lt $ListArrCnt ]] ; do if [[ ${ListArr[i]} == ${RecArr[1]} ]] ; then # We have matching record number ListArr[++i]="${RecArr[$ColFileDate]}" ListArr[++i]="${RecArr[$ColFileName]}" # File name should never change ListArr[++i]="${RecArr[$ColStatus]}" ListArr[++i]="${RecArr[$ColA_Votes]}" ListArr[++i]="${RecArr[$ColWebAddr]}" ListArr[++i]="${RecArr[$ColQ_Votes]}" ListArr[++i]="${RecArr[$ColTitle]}" let i=$(($ListArrCnt + 1)) # force exit from while loop else let i=$(($i + $RecArrCnt)) # Check next entry fi done return 0 } # UpdateOne () RecSelected=true # Overrides are below UpdateAllOrOne () { TITLE="websync" # dialog title TEXT="Update Entry ${RecArr[$ColFileName]}" # dialog text ICON="emblem-downloads" # window icon (appears in launcher) IMAGE="browser-download" # window image (appears in dialog) # Process a single entry if [[ $RecSelected == true ]] ; then echo "2:0" > "$PercentFile" # Just in case last time temp file wasn't removed # Repurpose yad progress bar as wget information message. CurrentEntry="${RecArr[$ColFileName]}" ( spawn-progress-multi $PercentFile \ '--multi-progress --center --auto-close --skip-taskbar --title "websync" --text "Update Entry $CurrentEntry" --window-icon $ICON --image $IMAGE --fixed --width=600 --height=200 --watch-bar2 --bar=Downloading:NORM --bar=Analyzing:NORM' \ 2 & ) UpdateOne ONE echo "2:100" > "$PercentFile" # Force progress display to shut down return $? fi MsgFileName="/tmp/websync-diff-"$(date +%s) echo "--- /Prefix for files on local drive" > $MsgFileName echo "+++ /Prefix for code in Stack Exchange answers" >> $MsgFileName echo "3:0" > "$PercentFile" # Just in case last time temp file wasn't removed # Repurpose yad progress bar as wget information message. CurrentEntry="${RecArr[$ColFileName]}" ( spawn-progress-multi $PercentFile \ "--multi-progress --center --auto-close --skip-taskbar --title "websync" --text `"`Update All Entries `"` --window-icon $ICON --image $IMAGE --fixed --width=1000 --height=200 --watch-bar3 --bar=Downloading:NORM --bar=Analyzing:NORM --bar=`"`Entry progress`"`:NORM" \ 3 & ) # Process all Entries local let k=0 RecArr[0]=false EndLoop=$(( ListArrCnt - 1 )) while [ $k -lt $EndLoop ] ; do let i=k RecArr[$ColRecNo]="${ListArr[++i]}" RecArr[$ColFileDate]="${ListArr[++i]}" RecArr[$ColFileName]="${ListArr[++i]}" RecArr[$ColStatus]="${ListArr[++i]}" RecArr[$ColA_Votes]="${ListArr[++i]}" RecArr[$ColWebAddr]="${ListArr[++i]}" RecArr[$ColQ_Votes]="${ListArr[++i]}" RecArr[$ColTitle]="${ListArr[++i]}" echo "2:0" > "$PercentFile" echo "3:"$(( $k*100/$ListArrCnt )) > "$PercentFile" echo "3:#""${RecArr[$ColFileName]}" > "$PercentFile" UpdateOne "$MsgFileName" [[ "$?" != "0" ]] && return "$?" ; # clicked close on progress dialog or wget error let k=$(($k + $RecArrCnt)) # next entry if [ $k -ge $EndLoop ] ; then echo "3:100" > "$PercentFile" fi done # If file doesn't exist, errors in diff parameters # If file size =0 there were no differences if [[ -f $MsgFileName ]] && [[ -s $MsgFileName ]] ; then gedit $MsgFileName fi return 0 } # UpdateAllOrOne () ExternalSortArray () { # Called on Save cp --preserve ~/.websync ~/.websync~ #Make backup copy IFS="|" read -ra ListArr < ~/.websync ListArrCnt=${#ListArr[@]} # echo "ListArrCnt: $ListArrCnt" # Can't sort empty file or array with 1 entry [[ $ListArrCnt -lt $(( $RecArrCnt + 1 )) ]] && return 0; # Create Keys Index echo " " echo "1. Create Keys-Index Pairs File" > ~/.websyncSort # Empty existing file. time for (( i=0; i<$ListArrCnt; i=i+$RecArrCnt )) ; do # Sort key = Question Title + Local File Name CurrKey="${ListArr[$(( $i + $ColTitle))]}${ListArr[$(( $i + $ColFileName))]//[^[:alnum:]\/]/}" echo "$CurrKey|$i" >> ~/.websyncSort done # Call external sort program echo " " echo "2. Sort Keys-Index Pairs File" time sort -k1 -t"|" ~/.websyncSort -o ~/.websyncSort # cat ~/.websyncSort # Strip out keys echo " " echo "3. Strip out keys leaving Sorted Indices" time cut -f2 -d '|' ~/.websyncSort > ~/.websyncNdx # cat ~/.websyncNdx echo " " echo "4. Rewrite List Array by Sorted Index" > ~/.websync # Empty existing ListArr[] file. RecNo=1 # Sequential record number Second="" time while read -r line; do j=$(( $line + $RecArrCnt )) FldNdx=0 for (( i=$line; i> ~/.websync RecNo=$(( $RecNo + 1 )) else echo -n "$Second""$LastChar" >> ~/.websync fi Second="|" FldNdx=$(( $FldNdx + 1 )) # Update progress display done done < ~/.websyncNdx echo " " printf "* * * ExternalSortArray -- " echo " Total elements: $ListArrCnt * * *" } ### ExternalSortArray () OldIFS="$IFS" IFS="|" ListArr=() IFS="|" read -ra ListArr < ~/.websync # Define variables for easy reading and fewer code line changes when expanding RecArrCnt=9 ListArrCnt=${#ListArr[@]} if [[ $ListArrCnt -lt $RecArrCnt ]] ; then # Handle empty file: Create dummy entries. ListArr+=("false" "1" "Update" "/boot/grub/grub.cfg" "Different" "Update") ListArr+=("http://askubuntu.com/questions/142293/different-grub-files-to-edit/142295#142295") ListArr+=("Update" "Dummy question.") ListArr+=("false" "2" "Update" "$HOME/.bashrc" "Different" "Update") ListArr+=("http://askubuntu.com/questions/820684/how-do-i-fix-the-terminal/820709#820709") ListArr+=("Update" "Dummy question.") ListArrCnt=${#ListArr[@]} fi TransCount=0 # Number of Inserts, Edits and Deletes ButnView=10 ButnInsert=20 ButnEdit=30 ButnDelete=40 ButnUpdate=50 ButnCancel=60 ButnSave=80 while true ; do if [[ $TransCount -eq 0 ]] ; then VariableCloseText="_Close" else VariableCloseText="_Cancel ALL" fi # adjust width & height below for your screen 1600x800 default for 1920x1080 HD # screen and adjust font="14" below if blue title text is too small or too large. Record=(`yad --list --separator="|" --skip-taskbar \ --title="websync - Compare code to answer posted on Stack Exchange." \ --text="Click column heading to sort.\ Select an entry before clicking: View / Insert / Edit / Delete / Update" \ --width=1600 --height=800 --center --radiolist --grid-lines=both --no-markup \ --button="_View":$ButnView --button="_Insert before":$ButnInsert \ --button="_Edit":$ButnEdit --button="_Delete":$ButnDelete \ --button="_Update":$ButnUpdate --button="$VariableCloseText":$ButnCancel \ --button="_Save":$ButnSave \ --search-column=3 --column "Select" --column "Record Number":HD \ --column "File Date":HD --column "File Name":FL --column "Status" \ --column "A+" --column "Stack Exchange":HD \ --column "Q+" --column "Question Title" \ "${ListArr[@]}"`) Action=$? RecSelected=false RecArr=() i=0 for Field in "${Record[@]}" ; do RecSelected=true RecArr[i++]=$Field done # Error checking if [[ $Action == $ButnView ]] || [[ $Action == $ButnInsert ]] || [[ $Action == $ButnEdit ]] \ || [[ $Action == $ButnDelete ]] ; then if [[ $RecSelected == false ]] ; then yad --error --text 'You must select a record before clicking: View / Insert / Edit / Delete.' --center continue fi fi # Insert before || or Edit ? if [ $Action == $ButnInsert ] || [ $Action == $ButnEdit ] ; then # After changing file name or Stack Exchange Address these must be updated. RecArr[$ColFileDate]="Update" RecArr[$ColStatus]="Update" RecArr[$ColA_Votes]="Update" RecArr[$ColQ_Votes]="Update" RecArr[$ColTitle]="Update" # --text="Set fields and click OK to update" # Note a space after \ generates invalid command error from yad NewRecArr=(`yad --form --width=900 --height=400 --center --skip-taskbar \ --title="Select a file name and link it to Stack Exchange" \ --text="Click OK to save. Click Cancel or press Escape to discard changes." \ --field="File date":RO --field="File name":FL --field="Status":RO \ --field="Answer +":RO --field="Stack Exchange Address":TXT \ --field="Question +":RO --field="Question Title":RO \ ${RecArr[$ColFileDate]} ${RecArr[$ColFileName]} ${RecArr[$ColStatus]} \ ${RecArr[$ColA_Votes]} ${RecArr[$ColWebAddr]} \ ${RecArr[$ColQ_Votes]} ${RecArr[$ColTitle]}`) ret=$? # Cancel =252, OK = 0 # OK & Insert operation? if [[ $ret == 0 ]] && [[ $Action == $ButnInsert ]]; then # Create new list entry and renumber ((TransCount++)) # Update number of changes let i=1 # Base 0 array, record number is second field while [ $i -lt $ListArrCnt ] ; do if [ ${ListArr[$i]} -eq ${RecArr[$ColRecNo]} ]; then # We have matching record number to insert before NewArr+=( false ) # Selected NewArr+=( "${RecArr[$ColRecNo]}" ) # Will be renumbered NewArr+=( "${NewRecArr[$NewFileDate]}" ) NewArr+=( "${NewRecArr[$NewFileName]}" ) NewArr+=( "${NewRecArr[$NewStatus]}" ) NewArr+=( "${NewRecArr[$NewA_Votes]}" ) NewArr+=( "${NewRecArr[$NewWebAddr]}" ) NewArr+=( "${NewRecArr[$NewQ_Votes]}" ) NewArr+=( "${NewRecArr[$NewTitle]}" ) fi let j=$(( $i-1 )) let k=$(( $j+$RecArrCnt )) while [ $j -lt $k ] ; do NewArr+=( "${ListArr[$j]}" ) j=$(($j + 1)) done let i=$(($i + $RecArrCnt)) # Next list array entry to copy done ListArr=("${NewArr[@]}") unset NewArr RenumberListArr # OK & Edit operation? elif [[ $ret == 0 ]] && [[ $Action == $ButnEdit ]]; then # Update array entry ((TransCount++)) let i=1 while [ $i -lt $ListArrCnt ] ; do if [ ${ListArr[$i]} -eq ${RecArr[1]} ]; then # We have matching record number ListArr[++i]="${NewRecArr[$NewFileDate]}" ListArr[++i]="${NewRecArr[$NewFileName]}" ListArr[++i]="${NewRecArr[$NewStatus]}" ListArr[++i]="${NewRecArr[$NewA_Votes]}" ListArr[++i]="${NewRecArr[$NewWebAddr]}" ListArr[++i]="${NewRecArr[$NewQ_Votes]}" ListArr[++i]="${NewRecArr[$NewTitle]}" let i=$(($ListArrCnt + 1)) # force exit from while loop else let i=$(($i + $RecArrCnt)) # Check next entry fi done else : # noop for readibility: Cancel or Escape pressed in Insert / Edit window fi # View or Delete record? elif [[ $Action == $ButnView ]] || [[ $Action == $ButnDelete ]] ; then # Note if there is a space after "\", the next line generates # "invalid command" error message from yad. if [[ $Action == $ButnDelete ]] ; then YadTitle="Do you really want to delete this entry?" YadText="Click OK to confirm delete." else YadTitle="websync - Single entry view mode" YadText="Click any button or press Escape after viewing entry." fi yad --width=900 --height=600 --form --center --skip-taskbar \ --title="$YadTitle" --text="$YadText" \ --field="File date":RO --field="File name":TXT --field="Status":RO \ --field="Answer +":RO --field="Stack Exchange Address":TXT \ --field="Question +":RO --field="Question Title":TXT \ ${RecArr[$ColFileDate]} ${RecArr[$ColFileName]} ${RecArr[$ColStatus]} \ ${RecArr[$ColA_Votes]} ${RecArr[$ColWebAddr]} ${RecArr[$ColQ_Votes]} \ ${RecArr[$ColTitle]} ret=$? if [[ $Action == $ButnView ]] ; then continue fi # Cancel =252, OK = 0 if [[ $ret == 0 ]] && [[ $Action == $ButnDelete ]] ; then # Delete record from list array and renumber ((TransCount++)) let i=1 while [ $i -lt $ListArrCnt ] ; do if [ ${ListArr[$i]} -eq ${RecArr[$ColRecNo]} ]; then # We have matching record number to delete j=$(($i - 1)) k=$(($j + $RecArrCnt)) while [ $j -lt $k ] ; do unset 'ListArr[$j]' j=$(($j + 1)) done for i in "${!ListArr[@]}"; do NewArr+=( "${ListArr[$i]}" ) done ListArr=("${NewArr[@]}") unset NewArr let i=$(($ListArrCnt + 1)) # force exit from while loop else let i=$(($i + $RecArrCnt)) # Check next entry fi done RenumberListArr else : # cancel delete operation. fi # Run update process? elif [[ $Action == $ButnUpdate ]] ; then time UpdateAllOrOne ret=$? # Cancel all changes or "252"= X the window or Escape? elif [[ $Action == $ButnCancel ]] || [[ $Action == 252 ]] ; then if [[ $TransCount -gt 0 ]] ; then (`yad --image "dialog-question" --title "websync - Exit confirmation." \ --text="You have made $TransCount change(s). Do you really want to exit?" \ --button=_Stay:1 --button=_Exit:2 --center`) if [[ $? -eq 2 ]] ; then exit fi else exit fi # Save changes? elif [[ $Action == $ButnSave ]] ; then # Save echo "${ListArr[*]}" > ~/.websync # Using * instead of @ preserves | ExternalSortArray exit else yad --error --center --text "websync - Unknown button return code: $Action" exit fi done IFS="$OldIFS" exit

spawn-progress-multi脚本

如果您没有在路径中放置spawn-progress-multi文件,则websync将无法运行它

 #!/bin/bash # NAME: spawn-progress-multi Percent=0 MYNAME=$0 /usr/bin/logger $MYNAME "multi-progress FIFO named pipe: $1" val="$2" /usr/bin/logger $MYNAME "multi-progress yad parameters: $2" /usr/bin/logger $MYNAME "multi-progress bar number to watch: $3" while true ; do # loop until 100 % # Percent=$(cat "$1") [[ -f "$1" ]] && read -r Percent < "$1" echo "$Percent" if [[ $Percent == *"$3:100"* ]] ; then break ; fi ; done | yad $2 exit 0 

介绍

由于Ask Ubuntu(AU)答案的32KB大小限制,此解决方案分为多个答案。

第一部分为用户指南提供屏幕截图和字段说明。

下一节提供了完成工作的bash脚本。

概观

所有Ask Ubuntu(AU)答案都以HTML(超文本标记语言)格式存储。 这个应用程序可以在所有Stack Exchange(SE)站点上运行,但它只有AU测试才有很高的可信度。

该申请将:

  • 提取问题标题
  • 提取问题upvotes
  • 提取答案upvotes
  • 提取与前三行包含代码的链接文件名匹配的SE代码
  • 在SE代码和本地代码之间运行diff命令,在gedit显示结果。
  • 显示进度条
  • 易于使用的GUI,没有终端要求
  • 除了复制bash脚本之外没有其他安装
  • 将样本数据附加到磁盘上的现有文件(Ubuntu 16.04)和现有答案。

示例主窗口

websync main.gif

这个演示屏必须快节奏,帧减少到2MB文件限制。 它显示首次运行脚本时创建的默认数据。 这是发生了什么:

  • 选择第二个条目
  • 单击“ Update按钮
  • wget从Stack Exchange下载问题和答案,简要介绍进度条。
  • 分析问题和答案,并显示进度条约3秒钟。
  • diff命令将本地代码~/.bashrc与Stack Exchange上的答案进行比较, gedit用于显示差异。

这是动画结束后遗漏的内容:

websync gedit.png

gedit用于显示本地代码~/.bashrc与堆栈交换答案之间的差异。

websync main 2.png

关闭gedit ,主屏幕重新出现,现在填写了问题 – 投票,回答 – 投票和问题标题字段。

让我们通过单击“ View按钮向下钻取

websync视图按钮

在这里,您可以看到主屏幕上不适合的条目的所有字段。 您可以将堆栈交换网站地址复制到clipbaord,然后将其粘贴到浏览器中。 您可以查看系统上存储的代码文件的上次修改日期。

状态”字段可以包含:

  • Update – 添加了新条目或更改了现有条目。 必须单击“更新”按钮以清除标记为更新的所有字段,并使用Stack Exchange中的实际值进行设置。
  • Bad file – 指定的文件名不再存在。
  • Empty file – 指定的文件名为零字节。
  • 3 lines not found – 在Stack Exchange答案中找不到指定文件的前三行(跳过空行)。 输入了错误的文件名或提供了错误的堆栈交换答案,或者文件已更改,使前三行不再匹配。
  • Bad Answer – 网站地址不存在。
  • Answer < 1K - 网站地址存在但答案的大小不到1 KB。
  • Different - 本地代码文件和Stack Exchange Answer有差异。
  • Matches - 本地代码文件与堆栈交换答案答案匹配。
  • Diff parameter Error - 用于调用diff命令的参数包含一个或多个错误。 使用man diff查看有效选项。

项目范围

主要目的是找出其他人已修改的答案,并将这些更改滚动到本地代码文件中。 另一个目的是找出在本地发生编码更改后需要更新Stack Exchange中的哪些答案。 最后,可以通过答案投票的跟踪来追踪“热门”答案。

不应使用SQL数据库。 只能使用out-of-the-box-bash文件。 应用程序必须使用yad作为GUI用户界面。 Zenity太有限,因为它无法在表单中显示原始值,在数据库太宽时无法隐藏列,并且不允许添加按钮来控制程序流。

解释上面显示的示例主窗口,它显示包含以下内容的可滚动条目:

  • 用于选择条目的单选按钮
  • 包含代码的本地文件名
  • 回答Up-votes(你发布的代码和书面答案正在收集)
  • 提问 - (表示全球对此SE问题的兴趣)
  • 问题标题

主窗口按钮的摘要是:

  • View - 查看所选条目。
  • Insert before - 在所选条目Insert before插入新条目。
  • Edit - 编辑所选条目。
  • Delete - 删除选择条目(需要确认)。
  • Update - 从Stack Exchange下载答案并进行分析。
  • Cancel ALL - 取消所有更改(如果已进行更改,则需要确认)。 退出键或窗口上的X具有相同的效果。
  • Save - 将更改保存到磁盘。

View和“ Delete按钮会弹出如上所示的同一窗口。

Insert before和“ Edit按钮会弹出类似的窗口,但某些字段未输入并使用“更新”进行初始化。 这表示需要单击主窗口上的“ Update按钮以便稍后从Stack Exchange检索数据。 非输入字段是:文件日期,状态,答案向上投票,提问题和标题。


2017年6月更新

修改了代码,以便在保存更改时按问题标题+本地文件名对数组条目进行排序。 不再需要按顺序手动插入记录。

您现在可以通过单击update按钮update all而不选择特定记录。 更新时,所有文件比较都会汇总到一个文件中,并在完成后由gedit显示。 具有相同源代码的答案不会在中断流程的对话框中显示,而是作为状态行放在diff文件中。

为按钮提供加速键。 按住Alt键 ,然后点击要选择的按钮的第一个字母。

sed需要3秒才能将HTML更改为文本太长时间。 它被内置的bash搜索和替换取代,时间现在是一秒或更短。

不幸的是,这些代码更改对于Ask Ubuntu发布来说太长了2000个字符,所以如果您想要一份代码,请留下评论,我会找到一些地方给您发布。