#] #] ********************* #] "$d_SysMaint""Linux/sed summary.txt" www.BillHowell.ca ?date? initial - maybe 2017or something? # view this file in a text editor, with [constant width font, tab = 3 spaces], no line-wrap 24************************24 #] sed cheat sheet : https://quickref.me/sed (not so useful, but nice overall) #] +-----+ #] examples : #] #] d_web : #] $ find "$d_web" -type f \( -name "*.html" \) | grep --invert-match -i "z_Old\|z_Archive" | sort | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number 'ary_indexA_convertTo_boolA' "FILE" | sed "s|$d_Qroot||;s|:.*||" | sort -u >"$d_temp"'find-grep-sed temp.txt' #] #] QNial dirs : #] $ find "$d_Qroot" -type f \( -name "*.ndf" -o -name "*.txt" \) | grep --invert-match -i "z_Old\|z_Archive" | sort | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number 'ary_indexA_convertTo_boolA' "FILE" | sed "s|$d_Qroot||;s|:.*||" | sort -u >"$d_temp"'find-grep-sed temp.txt' #] #] reverse str - to get middle part #] $ cat "$d_web"'webWork files/urls pLst base non-[webWork, conference guides].txt' | tr \\n \\0 | xargs -0 -IFILE grep --with-filename -i '\[#=; backtrack ;=#\]' "FILE" | sed 's|\(.*\):.*|\1|' | rev | sed 's|.*:||;s|\(.*\)\>".*|\1|' | rev | sort -u >"$d_web"'webWork files/urls pLst backtrack.txt' #] #] [quote, apo] :avoid the "greedy regexpr, be much more specific on [chr,word]s in searchExpr : # $ fNam='rawCsv SPX 1872-now TradingView.txt' #] $ sed 's|\"\([A-Za-z0-9]\+\)\,|"\1|g' "$d_mktData"'rawCsv/'"$fNam' | sed "s|NaN||g" >"$d_temp$fNam" #] #] [grep, sed] * [upper, lowr] case insensitive option -i #] $ cat "$d_web"'webWork files/urls pLst base non-[webWork, conference guides].txt' | tr \\n \\0 | xargs -0 -IFILE grep -i ".*|\1|gi' | rev | sed 's|>\(.*\)\"|\1|gi' | rev | sort -u >"$d_web"'webWork files/webDirL from links.txt' #] must have Ig format, not gi? : #] 's|.*.*|\1|Ig;s|.*"$ptmp" #] #] string only (not through a file) #] $ dTmp1="$d_temp"'dWeb1/' #] echo '/home/bill/web/ProjMini/TrNNs-ART/Introduction.html' | sed "s|/home/bill/web/ProjMini/TrNNs-ART/|$dTmp1|" #] #] +--+ #] -type [f, d] [f=file, d=directory] only one or the other $ find "$1" -maxdepth 1 -type f -name "$3" | sed 's#'$1'##g' >"$d_lst" $ find "$d_bads" -maxdepth 1 -type f -name "*.pdf" | sed "s#.*N-##g;s#\.pdf##g" >>"$p_badList" #] -type d directories only : $ find "$d_Qndfs" -maxdepth 1 -type d | sed "s|""$d_Qndfs""||" #] grep words (symbols) -w = word, -i = case insensitive $ find "$d_Qndfs" -type f -name "*.ndf" | grep --invert-match 'z_Archive' | grep --invert-match 'z_Old' | tr \\n \\0 | xargs -0 -ILINE grep -w -i --with-filename --line-number "str_to_phrases1" LINE #] -maxdepth 3 specify depth to search in directoryty tree $ find "/media/bill/SWAPPER/Website - raw/" -maxdepth 3 -name "*.html" | tr \\n \\0 | xargs -0 -IFILE grep -w -i --with-filename --line-number ':&file-insert &:' "FILE" | sed 's#:.*##' | sort -u #] "-atime -90" find files accessed less than 90 days ago $ find "$d_Qndfs" -atime -90 -type f -name "*.ndf" | grep --invert-match 'z_Archive' | grep --invert-match 'z_Old' | tr \\n \\0 | xargs -0 -ILINE grep --with-filename --line-number "_test" LINE | sed 's/^\(.*\):[0-9]\+:.*/\1/' | sort -u #] #] +-----+ #] output redirection #] 2> /dev/null - send stderr to void must come AFTER normal ">" to stdout (default 1) #] 2>&1 - send stderr to stdout must come AFTER normal ">" to stdout (default 1) #] #] send stderr to a stdout then to file, when stderr floods results Can I find old bash scripts? #] $ find / -type f -name "batch_access.sh" 2>&1 | tr \\n \\0 | xargs -0 -IFILE grep --invert-match "Permission denied" "FILE" $ find / -type f -name "batch_access.sh" 2>"/media/bill/ramdisk/permission denied.txt" $ grep --invert-match "Permission denied" "/media/bill/ramdisk/permission denied.txt" >"/media/bill/ramdisk/permission denied2.txt" $ grep --invert-match "Operation not permitted" "/media/bill/ramdisk/permission denied2.txt" >> Not found anywhere #] 08Mar2023 search 'Linux sed and how do I reference more than 9 items?' sequential seds >> yuch! but this gives me an idea to sequentially do a sed.. see 08Mar2023 in "$d_bin"'port bash to python.txt' #] #] +-----+ #] 255 maximum length of a sed expression #] +-----+ #] Special chrs, how to handled VERY safely (but slow!) : #] see : "$d_bin"'0_test/fileops/0_fileops test notes.txt' #] section : sed - [data, optr]s to convert between [original, code, escape] forms of text #] SEARCH side of sed : #] [^$\&'",*.[]{}-\|/] [escape, [chr], other] to search including regexpr special characters #] \"\' $'\x22' $'\x27' #] usually DON'T QUOTE `" sed expression for ['"], use apo `', eg sed 's/\'/~/' #] have to quote when variables involved, eg : #] echo 'cp "$pBash908" "$p1tmp908" ' | sed "s|\"\$\($sym\)\"|\1|" #] [(] [)] cannot backslash - means [start, end] of a series #] \, comma is sed OR separator in the bracket expression #] \n have to use |tr \'n' '\r' | sed | tr '\r' '\n' >... #] not easy to get this to work #] \t $ sed s'|\x9|xyZyx|' "$" | grep --invert-match 'xyZyx' (non-tabbed) #] bash by itself interprets $'\t' as tabulator #] Tbl of chrCodes - doesn't work in grep (at least not \n=??), maybe in sed? #] \x0 or \x00 sed -e 's/\x00/test/' null #] quote apo return tab backslash vertical forwdslash #] \d34=" \d39=' \d10=\n \d9=tab \d92=\ \d124-| \d47=/ #] \x22=" \x27=' \xA=\n \x9=tab \x5C=\ \7C=| \x2F=/ #] \o042=" \o047=' \o012=\n \o011=tab \o134=\ \o174=| \o057=/ #] "=" '=' "=\n "=tab "=\ "=| "=/ html #] http://www.asciitable.com/ https://unix.stackexchange.com/questions/32907/what-characters-do-i-need-to-escape-when-using-sed-in-a-sh-script +-----+ #] Special chrs : REPLACE side of sed : #] [/\&] only three literal characters which are treated specially in the replace clause #] [\n \t \\ ...] are not a problem as escaped chrs +-----+ #] Case insensitive: search and replace - I option after [one, both] sed separators: #] sed -n "/Account/Recognized/Ip" Security.txt #] #] +-----+ #] tabs example (should replace kwrite part to get sed-only!) #] echo " hello big" | sed 's|\x9|~:~|g' result : ~:~hello~:~big #] echo " hello big" | sed 's|\x9.*|~:~|g' result : ~:~ #] (in last example, only one tab replaced -> reverse greedy?) https://stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed #] tr is only the right tool for the job if replace a single character for a single character #] I couldn't get it to work simply - best with sed #] +-----+ +-----+ #] [#|!] sed alternative delimiters depending on [search, replace] terms!!! (any chr not in sExpr?) eg for directory strings $ find "/media/bill/PROJECTS/2019 IJCNN Budapest/papers/all - final/" -name "*.pdf" | sed 's#/media/bill/PROJECTS/2019 IJCNN Budapest/papers/all - final/N-##;s/.pdf//' | sort -u can mix [/,#] : cat "$p_format" | sed "s#1_Paper review form.txt#'$review'#;s/Paper : /Paper : '$2 $3'/;s/Assigned : /Assigned : '$1'/" >"$review" see "/media/bill/SWAPPER/bin/0_directory updates - bash & qnial.sh" process_dir() { mkdir "$2" find "$1" -maxdepth 1 -type f -name "$3" | sed 's#'$1'##g' >"$d_lst" while read -u 9 line; do cat "$1""$line" | sed "$4" >"$2""$line" done 9< "$d_lst" } #process_dir "$d_bin" "$d_bin_tmp" "*.sh" "s#/PROJECTS/#/SWAPPER/#g" process_dir "$d_ndf" "$d_ndf_tmp" "*.ndf" "s#/PROJECTS/#/SWAPPER/#g;s#/media/bill/HOWELL_BASE/#/media/bill/SWAPPER/#g;s#/home/bill/Qnial/#/media/bill/SWAPPER/Qnial/#g;s#/home/bill/nial/#/media/bill/SWAPPER/Qnial/#g;s#/home/bill/Languages/##g" +-----+ #] 's/str1/str2/gI' case insensitive match, -I option # https://www.cyberciti.biz/faq/unixlinux-sed-case-insensitive-search-replace-matching/ # Author: Vivek Gite Last updated: April 20, 2020 5 comments # cat file.txt | sed -e 's/find-word/replace-word/gI' https://www.cyberciti.biz/faq/unixlinux-sed-case-insensitive-search-replace-matching/ $ sed 's/first/last/Ig' file https://stackoverflow.com/questions/1032023/sed-whole-word-search-and-replace #] \b matches word boundaries example : $ echo "bar embarassment" | sed "s/\bbar\b/no bar/g" i.e. the location between the first word character and non-word character +-----+ #] '\'' put apo around the argument in the replacement text +-----+ #] "quote" sed special characters by preceding them by a backslash (if part of search expression) https://unix.stackexchange.com/questions/32907/what-characters-do-i-need-to-escape-when-using-sed-in-a-sh-script There are two levels of interpretation here: the shell, and sed. In the shell, everything between single quotes is interpreted literally, except for single quotes themselves. You can effectively have a single quotes between single quotes by writing '\'' (close single quote, one literal single quote, open single quote). Sed uses basic regular expressions. In a BRE, the characters $.*[\]^ need to be quoted by preceding them by a backslash, except inside character sets ([…]). Letters, digits and (){}+?| must not be quoted (you can get away with quoting some of these in some implementations). The sequences \(, \), \n, and in some implementations \{, \}, \+, \?, \| and other backslash+alphanumerics have special meanings. You can get away with not quoting $^] in some positions in some implementations. Furthermore, you need a backslash before / if it is to appear in the regex outside of bracket expressions. You can choose an alternate character as the delimiter by writing e.g. s~/dir~/replacement~ or \~/dir~p; you'll need a backslash before the delimiter if you want to include it in the BRE. If you choose a character that has a special meaning in a BRE and you want to include it literally, you'll need three backslashes; I do not recommend this. In a nutshell, for sed 's/…/…/': Write the regex between single quotes. Use '\'' to end up with a single quote in the regex. Put a backslash before $.*/[\]^ and only those characters (but not inside bracket expressions). Inside a bracket expression, for - to be treated literally, make sure it is first or last ([abc-] or [-abc], not [a-bc]) Inside a bracket expression, for ^ to be treated literally, make sure it is not first (use [abc^], not [^abc]) To include ] in the list of characters matched by a bracket expression, make it the first character (or first after ^ for a negated set): []abc] or [^]abc] (not [abc]] nor [abc\]]). In the replacement text: & and \ need to be quoted, as do the delimiter (usually /) and newlines. \ followed by a digit has a special meaning. \ followed by a letter has a special meaning (special characters) in some implementations, and \ followed by some other character means \c or c depending on the implementation. With single quotes around the argument (sed 's/…/…/'), use '\'' to put a single quote in the replacement text. If the regex or replacement text comes from a shell variable, remember that the regex is a BRE, not a literal string; in the regex, a newline needs to be expressed as \n (which will never match unless you have other sed code adding newline characters to the pattern space). But note that it won't work inside bracket expressions with some sed implementations; in the replacement text, &, \ and newlines need to be quoted; the delimiter needs to be quoted (but not inside bracket expressions). Use double quotes for interpolation: sed -e "s/$BRE/$REPL/" shareimprove this answer edited Oct 24 '17 at 12:20 Stéphane Chazelas 249k45446740 answered Feb 29 '12 at 1:06 Gilles +-----+ #] \'$'\n how-to-insert-a-newline-in-front-of-a-pattern # https://stackoverflow.com/questions/723157/how-to-insert-a-newline-in-front-of-a-pattern sed - insert newline as in cat "$paper_tbk" | grep "|>" | sed 's/\(.*\)\(<|\)\(.*\)\(|>\)\(.*\)/\3\'$'\n/' sed wildcard ".*" not "?*" +-----+ #] \(.\)\{12\} ignore a character sequence of specified length (could use cut here?) $ cat "/media/bill/PROJECTS/2019 IJCNN Budapest/Publications/CrossCheck/190112 CrossCheck similarities for papers on hand.txt" | sed 's/^\(.\)\{12\}\(.*\)/\2/' >"/media/bill/ramdisk/190118 CrossCheck nodate.txt" +-----+ #] [A-Za-z0-9._-] character ranges 's/\([^0-9]\+\)\([0-9]\+\)\(\.\)\([0-9]\+\)\(.*\)/\2\3\4/' from "$d_bin""email - remove emails from text file.sh" d_remove_emails() { if [ -d "$d_withEml" ]; then if [ -d "$d_noEmail" ]; then find "$d_withEml" -maxdepth 1 -type f -name "*" | sed "s#$d_withEml##" >"$d_temp""d_remove_emails files.txt" while read -u 9 line; do cat "$d_withEml""$line" | sed 's/[A-Za-z0-9._-]*@[A-Za-z0-9._-]*//g' >"$d_noEmail""$line" done 9< "$d_temp""d_remove_emails files.txt" else echo "directory doesnt exist : $d_noEmail" fi else echo "directory doesnt exist : $d_withEml" fi } #] +-----+ #] multiple stuffs +-----+ #] 's/ab/~~/;s/cd/ab/;s/~~/cd/' multiple text replacements in same sed 13Apr2019 #] where you KNOW that "~~" doesn't appear in the stream (eg null \x0) echo 'abcd' | sed -e 's/ab/~~/;s/cd/ab/;s/~~/cd/' find "$d_bads" -maxdepth 1 -type f -name "*.pdf" | sed "s#.*N-##g;s#\.pdf##g" >>"$p_badList" +-----+ #] multiple seds inline - eg 's|/media/bill/Dell2/Website - raw/||;s/\(.*\):[0-9]*:\(.*\)/\1/' case insensitive, replacement | as sed separator, escaping problematic characters, replace %20 with space (dangerous - not just in links! mailtos!!!!), brute force - just sequence to a max of 4 : $ cat "$p_webPage" | grep invert-match "mailto:" | grep --invert-match '|[#\!: path_insertIn_fHand (link d_webWork \"\1\") fout |;s|%20| |g;s|> this works but is ugly and probably inefficient >> there must be a way to cleanly get multiple-sequenced (repeated) strings #] +-----+ #] extract characters by position : $ echo "$date_ymdhm_new" | sed 's/^\(.\{2\}\).*/\1/' see "$d_bin""strings.sh" #] sed ':a;N;$!ba;s/\n//g;??s/ABC\nXYZ/ newfile #] sed -n '8000{p;q}' file - get nth line of a file #] +-----+ #] [variables, sort, du_diff, etc] +-----+ #] "s|$2|$3|" variables in sed fileops.sh examples where variables are paths, so `| used instead of `/ 22Jun2021 grep "$2" "$1" | sed "s|$2|$3|" >>"$p_temp" grep --with-filename --line-number "$2" "$FILE" | grep "$FILE" | sed "s|\($FILE\)\(.*\)|\1|g" | sort -u >>"$3" +-----+ #] | sort - -u use sort following sed $ find "$d_Qndfs" -type f -name "*.ndf" | grep --invert-match "z_Old\|z_Archive" | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number "path_exists" "FILE" | sed 's|/media/bill/Dell2/Website - raw/Qnial/MY_NDFS/||;s/\(.*\):[0-9]*:\(.*\)/\1/' | sort - -u +-----+ #] du_diff separation of input-unique lines see "/media/bill/SWAPPER/bin/rsync directories.sh" du_diff 1 "/media/bill/SWAPPER/" "/media/bill/SWAPPER2/" cat "$d_temp""du2.txt" | sed "s#$3#$2#" >"$d_temp""du2to1.txt" #] +-----+ #] work across path Lists +-----+ #] replace a string in many files, see also fileops.sh!!! - well set up #] $ find "$d_Qndfs" -type f -name "*.ndf" | grep | xargs -0 -IFILE grep | sed ... $ find "$d_Qndfs" -type f -name "*.ndf" | grep --invert-match "z_Old\|z_Archive" | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number "path_exists" "FILE" | sed 's|/media/bill/Dell2/Website - raw/Qnial/MY_NDFS/||;s/\(.*\):[0-9]*:\(.*\)/\1/' | sort - -u >"$d_temp""path_exists in Qndfs.txt" $ find "$d_webRawe" -type f -name "*.ndf" | grep --invert-match "z_Old\|z_Archive\|Qnial/MY_NDFS/" | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number "path_exists" "FILE" | sed 's|/media/bill/Dell2/Website - raw/||;s/\(.*\):[0-9]*:\(.*\)/\1/' | sort - -u >"$d_temp""path_exists outside of Qndfs.txt" #] +-----+ #] using sed with QNial # loaddefs link d_QNial_mine 'Website updates.ndf' update_webSite IS OP webSite { LOCAL cmd page p_webPageList webPageList ; NONLOCAL d_QNial_temp ds_base dw_base ; p_webPageList := link d_QNial_temp 'webPageList.txt' ; % find all html files with a ':@file-insert@:' ; cmd := link 'find "' webSite '" -maxdepth 3 -name "*.html" | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number ":@file-insert@:" "FILE" | sed "s#:.*##" | sort -u >"' p_webPageList '" ' ; host cmd ; } Also - more general if [apo,quote] not a problem - QNial : qnial> pathList := host_result (link 'find "$d_webRawe""Paul L Vaughan/" -type f -name "*.html"') qnial> str_replaceIn_pathList l (link d_webRawe 'z_Archive/210525 backups/') '/media/bill/Dell2/Website - raw/' '' pathList >> this also produces file backups #] +-----+ #] good general examples #] find recently accessed files containing a stringsort unique paths # "-atime -90" means any file accessed less than 90 days ago #] 's/^\(.*\):[0-9]\+:.*/\1/' $ find "$d_Qndfs" -atime -90 -type f -name "*.ndf" | grep --invert-match 'z_Archive' | grep --invert-match 'z_Old' | tr \\n \\0 | xargs -0 -ILINE grep --with-filename --line-number "_test" LINE | sed 's/^\(.*\):[0-9]\+:.*/\1/' | sort -u >> OK, still lists MANY files!! #] 's/\(.*\):[0-9]*:\(.*\)/\1/' $ find "$d_Qndfs" -type f -name "*.ndf" | grep --invert-match "z_Old\|z_Archive" | tr \\n \\0 | xargs -0 -IFILE grep --with-filename --line-number "path_exists" "FILE" | sed 's|/media/bill/Dell2/Website - raw/Qnial/MY_NDFS/||;s/\(.*\):[0-9]*:\(.*\)/\1/' | sort - -u #] grep --with-filename --line-number "$2" "$FILE" | grep "$FILE" | sed "s|\($FILE\)\(.*\)|\1|g" $ grep --with-filename --line-number "$2" "$FILE" | grep "$FILE" | sed "s|\($FILE\)\(.*\)|\1|g" | sort -u >>"$3" CrossCheck Split comments into criteria : $ cat "$p_inn" | sed 's/ : /\t/' | sed 's/ page, /\t/' | sed 's/max//' | sed 's/ one /\t/' | sed 's/source//' | sed 's/self-/self/' | sed 's/(could be external?)/external?/g' | sed 's/ //g' | sed 's/,//g' This is ugly! fix later!!! "/home/bill/System_maintenance/ssh/0_ssh notes.txt" $ cat "users - IJCNN2019 OrgCom - full email.txt" | sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/'| sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/' | sed 's/\(.*\)\(\. \)\(.*\)/\1/' >"users - IJCNN2019 OrgCom - names.txt" #] ******** #] KEY SOLUTION! [search. replace] general text - encode in alpha chrs, then process!! 04Aug2023 see fileops.sh section "str search-replace using sed" and "$d_bin"'0_test/fileops/fileops test.sh' #] too much screwing around with code, which always screws up #] sedFwd='s#\&#zaz#g;s#\"#zdqz#g;s#\,#zcz#g;s#\.#zpz#g;... #] sedBck='s#zaz#\&#g;s#zdqz#\"#g;s#zcz#\,#g;s#zpz#\.#g;... #] str_sedEscSearch() : echo "$1" | sed "$sedFwd" | sed "$sedEscApo" #] +-----+ #] differences [sed, kwrite] regexpr searches sed \(.*\)\+ \x9 (tab) not surethis works kwrite (.*)+ [\x9] # enddoc