1
\$\begingroup\$

I have a bash script that fixes or creates, and syncs the asciidoc attributes and yaml header for blog posts. It does what it is supposed to. But notice I have put sleep commands in between the sed -i insert commands. This is because I was getting unusual error messages such as:

sed: -e expression #1, char 40: unknown command: `Y'

But there is no command or any expression containing a Y in the file. I figured it was perhaps some kind of race condition, and wanted to 'slow' sed down. This sees to solve the problem but is there a better way to do this?

#!/usr/bin/bash      
#Before runing this script ensure the doc has a valid asciidoctor title    
#then set the type lang and author defaults    
    
export sectnumlevels=2    
export toc="true"    
export includedir="include"    
    
[[ -z "$1" ]] && { echo "need a file" ; exit 1 ; }    
sed -n '/^=\s/q1' "$1" && { echo "this looks like it doesn't have a title" ; exit 1 ; }    
export file=$1    
#delete blank lines    
sed -i '10,19{/^[[:space:]]*$/d}' "$1"-    
    
export title=`sed -n /^\=\ .*/p "$1"`-    
export author=`awk /author:/{'first = $1; $1=""; print $0'} "$1" |sed 's/^ //g'`    
export categories=`awk /categories:/{'first = $1; $1=""; print $0'} "$1" |sed 's/^ //g'`    
export tags=`awk /tags:/{'first = $1; $1=""; print $0'} "$1" |sed 's/^ //g'`    
    
[[ -z $author ]] && author="Name AUTHOR"    
export date=`awk '/date:/{print $2}' "$1" | uniq`-    
[[ -z "$date" ]] && date=`date -Im`    
export type="post"    
export lang="fr"    
export draft="true"    
[[ -z $categories ]] && categories="[]"    
[[ -z $tags ]] && tags="[]"    

function yaml {
  sed -i '1 i ---' "$file"
  sed -i "/^---/a title: $title" "$file"
  sed -i "/^title:/a author: $author" "$file"
  sed -i "/^author:/a date: $date" "$file"   
  sed -i "/^date:/a type: $type" "$file"     
  sed -i "/^type:/a draft: $draft" "$file"   
  sed -i "/^draft:/a categories: $categories" "$file"
  sed -i "/^categories:/a tags: $tags" "$file"
  sed -i '/^tags:/a ---' "$file"
  #this is the weirdest hack    
  sed -i '9 a #;' "$file" && sed -i 's/^#;//g' "$file"
}


#call yaml function if no yaml header
sed -r -n '/^---(\s|$)/q1' "$1" &&  yaml-

#but if there is already a header it may be missing stuff
#needs to take care of when the key exists but no value...
sed -n '/^title:\s/q1' "$1" &&  sed -i "/^---/a title: $title" "$file"
sed -n '/^author:\s/q1' "$1" &&  sed -i "/^title:/a author: $author" "$file"
[[ ! $(awk '/^date:/{print $2}' "$1") ]] &&  sed -i "/^author:/a date: $date" "$file"
sed -n '/^type:\s/q1' "$1" &&  sed -i "/^date:/a type: $post" "$file"



#start the asciidoctor attributes
sed -i '/^:author:.*/d' "$1" &&  sed -i "/^=\s/a :author: $author" "$1"
#[[ ! $(awk '/^:date:/{print $2}' "$1") ]] && sed -i "/^:author:/a :date: $date" "$1"
sleep 0.25-
sed -i '/^:date:.*/d' "$1" &&  sed -i "/^:author:/a :date: $date" "$1"
sleep 0.25-
sed -i '/^:type:.*/d' "$1" && sed -i "/^:date:/a :type: $type" "$1"
sleep 0.25-
sed -i '/^:toc:.*/d' "$1" &&  sed -i "/^:type:/a :toc: $toc" "$1"-
sleep 0.25-
sed -i '/^:experimental:.*/d' "$1" &&  sed -i '/^:toc:/a :experimental:' "$1"-
sleep 0.25-
sed -i '/^:sectnums:.*/d' "$1" && sed -i '/^:experimental:/a :sectnums:' "$1"
sleep 0.25-
sed -i '/^:sectnumlevels:.*/d' "$1" &&  sed -i "/^:sectnums:/a :sectnumlevels: $sectnumlevels" "$1"-

if [ ! $lang = "en" ]; then
  sed -n '/^:lang:\s/q1' "$1" &&  sed -i "/^:sectnumlevels:/a :lang: $lang" "$1"-
sleep 0.25-
  sed -i '/:includedir:.*/d' "$1" && sed -i "/^:lang:/i :includedir: content/$lang/$includedir" "$1"
sleep 0.25-
  sed -i '/include::locale/d' "$1" &&  sed -i '/^:lang:/a include::locale/attributes.adoc[]' "$1"-
sleep 0.25-
  sed -i "/^include::locale/a #;" "$1" && sed -i 's/^#;//g' "$1"
fi

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This question could be improved by showing a simple set of inputs and outputs, so we can replicate your results. It looks like your code has been mis-copied somehow - a lot of lines seem to have had - added at the end. I assume they are not in your actual script? Could you edit to fix them? \$\endgroup\$ Commented May 24, 2021 at 7:13

1 Answer 1

1
\$\begingroup\$
export sectnumlevels=2    
export toc="true"    
export includedir="include"

It's not clear why any of these need to be exported

[[ -z "$1" ]] && { echo "need a file" ; exit 1 ; }

Error messages should go to stderr, not stdout: echo >&2. And we could use portable shell [ instead of [[, rather than making the script Bash-specific.

  sed -i '1 i ---' "$file"
  sed -i "/^---/a title: $title" "$file"
  sed -i "/^title:/a author: $author" "$file"
  sed -i "/^author:/a date: $date" "$file"   
  sed -i "/^date:/a type: $type" "$file"     
  sed -i "/^type:/a draft: $draft" "$file"   
  sed -i "/^draft:/a categories: $categories" "$file"
  sed -i "/^categories:/a tags: $tags" "$file"
  sed -i '/^tags:/a ---' "$file"

It's inefficient to repeatedly open and write $file. Replace all this with a single sed program that inserts all of the required lines before line 1.

\$\endgroup\$
2
  • \$\begingroup\$ Ah but the point is there are old posts that may or may not have some or any of those lines. So the script searches for what exists already and inserts what is needed. \$\endgroup\$
    – Boyd
    Commented May 25, 2021 at 22:54
  • \$\begingroup\$ And your test cases verify that it does that correctly? As I commented on the question, you'll get better reviews if you can show some inputs and expected outputs (or better still, your complete test harness). \$\endgroup\$ Commented May 26, 2021 at 7:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.