[{"data":1,"prerenderedAt":1943},["ShallowReactive",2],{"page-\u002Flinux\u002F05-text-processing":3},{"id":4,"title":5,"body":6,"description":1936,"extension":1937,"meta":1938,"navigation":395,"path":1939,"seo":1940,"stem":1941,"__hash__":1942},"content\u002Flinux\u002F05-text-processing.md","05 — Text Processing & Pipelines",{"type":7,"value":8,"toc":1897},"minimark",[9,13,49,54,65,148,154,361,370,426,432,436,515,519,579,586,617,623,639,643,813,817,840,846,942,948,992,998,1009,1083,1089,1098,1187,1193,1303,1307,1311,1335,1339,1380,1384,1438,1442,1537,1541,1703,1707,1710,1750,1753,1893],[10,11,5],"h1",{"id":12},"_05-text-processing-pipelines",[14,15,16,17,21,22,26,27,26,30,26,33,26,36,26,39,26,42,26,45,48],"p",{},"Linux philosophy: write small tools that do one thing well, then combine them with ",[18,19,20],"strong",{},"pipes",". This chapter covers the core text-processing toolkit — ",[23,24,25],"code",{},"grep",", ",[23,28,29],{},"sed",[23,31,32],{},"awk",[23,34,35],{},"cut",[23,37,38],{},"sort",[23,40,41],{},"uniq",[23,43,44],{},"tr",[23,46,47],{},"xargs"," — composed into production-grade one-liners. This is arguably the most important skill for a Linux engineer.",[50,51,53],"h2",{"id":52},"pipes-recap","Pipes (Recap)",[14,55,56,57,60,61,64],{},"A pipe ",[23,58,59],{},"|"," connects one command's stdout to the next command's stdin. Each command runs ",[18,62,63],{},"concurrently",":",[66,67,69],"code-wrapper",{"language":68},"bash",[70,71,75],"pre",{"className":72,"code":73,"language":68,"meta":74,"style":74},"language-bash shiki shiki-themes github-light github-dark","# Complex Implementation: frequency-count top IPs in an access log\n# — 5 stages, all running concurrently, streaming data through the pipe\nawk '{print $1}' \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log | sort | uniq -c | sort -rn | head -10\n#  1243 192.168.1.50\n#   872 10.0.0.15\n","",[23,76,77,86,92,136,142],{"__ignoreMap":74},[78,79,82],"span",{"class":80,"line":81},"line",1,[78,83,85],{"class":84},"sdCPZ","# Complex Implementation: frequency-count top IPs in an access log\n",[78,87,89],{"class":80,"line":88},2,[78,90,91],{"class":84},"# — 5 stages, all running concurrently, streaming data through the pipe\n",[78,93,95,98,102,105,109,112,114,117,121,123,125,128,130,133],{"class":80,"line":94},3,[78,96,32],{"class":97},"sIsaT",[78,99,101],{"class":100},"sJ6F3"," '{print $1}'",[78,103,104],{"class":100}," \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log",[78,106,108],{"class":107},"svdQ7"," |",[78,110,111],{"class":97}," sort",[78,113,108],{"class":107},[78,115,116],{"class":97}," uniq",[78,118,120],{"class":119},"snvgF"," -c",[78,122,108],{"class":107},[78,124,111],{"class":97},[78,126,127],{"class":119}," -rn",[78,129,108],{"class":107},[78,131,132],{"class":97}," head",[78,134,135],{"class":119}," -10\n",[78,137,139],{"class":80,"line":138},4,[78,140,141],{"class":84},"#  1243 192.168.1.50\n",[78,143,145],{"class":80,"line":144},5,[78,146,147],{"class":84},"#   872 10.0.0.15\n",[50,149,151,153],{"id":150},"grep-search",[23,152,25],{}," — Search",[66,155,156],{"language":68},[70,157,159],{"className":72,"code":158,"language":68,"meta":74,"style":74},"grep \"root\" \u002Fetc\u002Fpasswd               # basic search\ngrep -r \"PermitRoot\" \u002Fetc\u002Fssh         # recursive\ngrep -i \"error\" \u002Fvar\u002Flog\u002Fsyslog       # case-insensitive\ngrep -v \"DEBUG\" app.log               # invert (lines WITHOUT \"DEBUG\")\ngrep -n \"PermitRoot\" sshd_config      # line numbers\ngrep -c \"error\" app.log               # count matches\ngrep -E \"^[0-9]+\" file                # extended regex (-E)\ngrep -w \"the\" file                    # whole-word match\ngrep -A 2 -B 2 \"error\" log            # 2 lines After, 2 Before\ngrep -l \"TODO\" *.py                   # only filenames with matches\ngrep -P \"(?\u003C=foo)bar\" file            # PCRE (lookbehind) — GNU grep\ngrep -oE 'https?:\u002F\u002F[^ ]+' access.log  # extract only matching portion\n",[23,160,161,174,190,206,222,237,251,268,284,308,328,344],{"__ignoreMap":74},[78,162,163,165,168,171],{"class":80,"line":81},[78,164,25],{"class":97},[78,166,167],{"class":100}," \"root\"",[78,169,170],{"class":100}," \u002Fetc\u002Fpasswd",[78,172,173],{"class":84},"               # basic search\n",[78,175,176,178,181,184,187],{"class":80,"line":88},[78,177,25],{"class":97},[78,179,180],{"class":119}," -r",[78,182,183],{"class":100}," \"PermitRoot\"",[78,185,186],{"class":100}," \u002Fetc\u002Fssh",[78,188,189],{"class":84},"         # recursive\n",[78,191,192,194,197,200,203],{"class":80,"line":94},[78,193,25],{"class":97},[78,195,196],{"class":119}," -i",[78,198,199],{"class":100}," \"error\"",[78,201,202],{"class":100}," \u002Fvar\u002Flog\u002Fsyslog",[78,204,205],{"class":84},"       # case-insensitive\n",[78,207,208,210,213,216,219],{"class":80,"line":138},[78,209,25],{"class":97},[78,211,212],{"class":119}," -v",[78,214,215],{"class":100}," \"DEBUG\"",[78,217,218],{"class":100}," app.log",[78,220,221],{"class":84},"               # invert (lines WITHOUT \"DEBUG\")\n",[78,223,224,226,229,231,234],{"class":80,"line":144},[78,225,25],{"class":97},[78,227,228],{"class":119}," -n",[78,230,183],{"class":100},[78,232,233],{"class":100}," sshd_config",[78,235,236],{"class":84},"      # line numbers\n",[78,238,240,242,244,246,248],{"class":80,"line":239},6,[78,241,25],{"class":97},[78,243,120],{"class":119},[78,245,199],{"class":100},[78,247,218],{"class":100},[78,249,250],{"class":84},"               # count matches\n",[78,252,254,256,259,262,265],{"class":80,"line":253},7,[78,255,25],{"class":97},[78,257,258],{"class":119}," -E",[78,260,261],{"class":100}," \"^[0-9]+\"",[78,263,264],{"class":100}," file",[78,266,267],{"class":84},"                # extended regex (-E)\n",[78,269,271,273,276,279,281],{"class":80,"line":270},8,[78,272,25],{"class":97},[78,274,275],{"class":119}," -w",[78,277,278],{"class":100}," \"the\"",[78,280,264],{"class":100},[78,282,283],{"class":84},"                    # whole-word match\n",[78,285,287,289,292,295,298,300,302,305],{"class":80,"line":286},9,[78,288,25],{"class":97},[78,290,291],{"class":119}," -A",[78,293,294],{"class":119}," 2",[78,296,297],{"class":119}," -B",[78,299,294],{"class":119},[78,301,199],{"class":100},[78,303,304],{"class":100}," log",[78,306,307],{"class":84},"            # 2 lines After, 2 Before\n",[78,309,311,313,316,319,322,325],{"class":80,"line":310},10,[78,312,25],{"class":97},[78,314,315],{"class":119}," -l",[78,317,318],{"class":100}," \"TODO\"",[78,320,321],{"class":119}," *",[78,323,324],{"class":100},".py",[78,326,327],{"class":84},"                   # only filenames with matches\n",[78,329,331,333,336,339,341],{"class":80,"line":330},11,[78,332,25],{"class":97},[78,334,335],{"class":119}," -P",[78,337,338],{"class":100}," \"(?\u003C=foo)bar\"",[78,340,264],{"class":100},[78,342,343],{"class":84},"            # PCRE (lookbehind) — GNU grep\n",[78,345,347,349,352,355,358],{"class":80,"line":346},12,[78,348,25],{"class":97},[78,350,351],{"class":119}," -oE",[78,353,354],{"class":100}," 'https?:\u002F\u002F[^ ]+'",[78,356,357],{"class":100}," access.log",[78,359,360],{"class":84},"  # extract only matching portion\n",[362,363,365,366,369],"h3",{"id":364},"performance-tip-lc_allc-grep-for-huge-files","Performance Tip: ",[23,367,368],{},"LC_ALL=C grep"," for Huge Files",[66,371,372],{"language":68},[70,373,375],{"className":72,"code":374,"language":68,"meta":74,"style":74},"# NAIVE: locale-aware grep on a 10 GB log (slow — UTF-8 collation overhead)\ngrep \"error\" huge.log\n\n# PRODUCTION: byte-wise grep (10x+ faster on large files)\nLC_ALL=C grep \"error\" huge.log\n# C locale = byte comparison, no Unicode processing\n",[23,376,377,382,391,397,402,421],{"__ignoreMap":74},[78,378,379],{"class":80,"line":81},[78,380,381],{"class":84},"# NAIVE: locale-aware grep on a 10 GB log (slow — UTF-8 collation overhead)\n",[78,383,384,386,388],{"class":80,"line":88},[78,385,25],{"class":97},[78,387,199],{"class":100},[78,389,390],{"class":100}," huge.log\n",[78,392,393],{"class":80,"line":94},[78,394,396],{"emptyLinePlaceholder":395},true,"\n",[78,398,399],{"class":80,"line":138},[78,400,401],{"class":84},"# PRODUCTION: byte-wise grep (10x+ faster on large files)\n",[78,403,404,408,411,414,417,419],{"class":80,"line":144},[78,405,407],{"class":406},"ssxIu","LC_ALL",[78,409,410],{"class":107},"=",[78,412,413],{"class":100},"C",[78,415,416],{"class":97}," grep",[78,418,199],{"class":100},[78,420,390],{"class":100},[78,422,423],{"class":80,"line":239},[78,424,425],{"class":84},"# C locale = byte comparison, no Unicode processing\n",[50,427,429,431],{"id":428},"sed-stream-editor",[23,430,29],{}," — Stream Editor",[362,433,435],{"id":434},"substitution","Substitution",[66,437,438],{"language":68},[70,439,441],{"className":72,"code":440,"language":68,"meta":74,"style":74},"sed 's\u002Fold\u002Fnew\u002F' file           # replace first occurrence per line\nsed 's\u002Fold\u002Fnew\u002Fg' file          # replace ALL occurrences per line (global)\nsed 's\u002Fold\u002Fnew\u002Fgi' file         # global + case-insensitive\nsed 's|\u002Fusr\u002Flocal|\u002Fopt\u002Fapp|g' file   # use | as delimiter (easier with \u002F)\nsed 's\u002F[[:space:]]*$\u002F\u002F' file    # trim trailing whitespace\nsed 's\u002F^[[:space:]]*\u002F\u002F' file    # trim leading whitespace\n",[23,442,443,455,467,479,491,503],{"__ignoreMap":74},[78,444,445,447,450,452],{"class":80,"line":81},[78,446,29],{"class":97},[78,448,449],{"class":100}," 's\u002Fold\u002Fnew\u002F'",[78,451,264],{"class":100},[78,453,454],{"class":84},"           # replace first occurrence per line\n",[78,456,457,459,462,464],{"class":80,"line":88},[78,458,29],{"class":97},[78,460,461],{"class":100}," 's\u002Fold\u002Fnew\u002Fg'",[78,463,264],{"class":100},[78,465,466],{"class":84},"          # replace ALL occurrences per line (global)\n",[78,468,469,471,474,476],{"class":80,"line":94},[78,470,29],{"class":97},[78,472,473],{"class":100}," 's\u002Fold\u002Fnew\u002Fgi'",[78,475,264],{"class":100},[78,477,478],{"class":84},"         # global + case-insensitive\n",[78,480,481,483,486,488],{"class":80,"line":138},[78,482,29],{"class":97},[78,484,485],{"class":100}," 's|\u002Fusr\u002Flocal|\u002Fopt\u002Fapp|g'",[78,487,264],{"class":100},[78,489,490],{"class":84},"   # use | as delimiter (easier with \u002F)\n",[78,492,493,495,498,500],{"class":80,"line":144},[78,494,29],{"class":97},[78,496,497],{"class":100}," 's\u002F[[:space:]]*$\u002F\u002F'",[78,499,264],{"class":100},[78,501,502],{"class":84},"    # trim trailing whitespace\n",[78,504,505,507,510,512],{"class":80,"line":239},[78,506,29],{"class":97},[78,508,509],{"class":100}," 's\u002F^[[:space:]]*\u002F\u002F'",[78,511,264],{"class":100},[78,513,514],{"class":84},"    # trim leading whitespace\n",[362,516,518],{"id":517},"in-place-editing","In-Place Editing",[66,520,521],{"language":68},[70,522,524],{"className":72,"code":523,"language":68,"meta":74,"style":74},"# Complex Implementation: safe in-place edit with backup\nsed -i.bak 's\u002Fold\u002Fnew\u002Fg' file       # in-place + save original as file.bak\n# Test WITHOUT -i first:\nsed 's\u002Fold\u002Fnew\u002Fg' file | head       # verify output, then apply with -i.bak\n\n# Anti-Pattern: sed -i without backup (no undo if regex is wrong)\n# sed -i 's\u002Fold\u002Fnew\u002Fg' file         → if wrong, file is corrupted\n",[23,525,526,531,545,550,565,569,574],{"__ignoreMap":74},[78,527,528],{"class":80,"line":81},[78,529,530],{"class":84},"# Complex Implementation: safe in-place edit with backup\n",[78,532,533,535,538,540,542],{"class":80,"line":88},[78,534,29],{"class":97},[78,536,537],{"class":119}," -i.bak",[78,539,461],{"class":100},[78,541,264],{"class":100},[78,543,544],{"class":84},"       # in-place + save original as file.bak\n",[78,546,547],{"class":80,"line":94},[78,548,549],{"class":84},"# Test WITHOUT -i first:\n",[78,551,552,554,556,558,560,562],{"class":80,"line":138},[78,553,29],{"class":97},[78,555,461],{"class":100},[78,557,264],{"class":100},[78,559,108],{"class":107},[78,561,132],{"class":97},[78,563,564],{"class":84},"       # verify output, then apply with -i.bak\n",[78,566,567],{"class":80,"line":144},[78,568,396],{"emptyLinePlaceholder":395},[78,570,571],{"class":80,"line":239},[78,572,573],{"class":84},"# Anti-Pattern: sed -i without backup (no undo if regex is wrong)\n",[78,575,576],{"class":80,"line":253},[78,577,578],{"class":84},"# sed -i 's\u002Fold\u002Fnew\u002Fg' file         → if wrong, file is corrupted\n",[362,580,582,583,585],{"id":581},"edge-case-sed-regex-is-bre-by-default","Edge Case: ",[23,584,29],{}," Regex is BRE by Default",[66,587,588],{"language":68},[70,589,591],{"className":72,"code":590,"language":68,"meta":74,"style":74},"# NAIVE: sed 's\u002Fa+\u002Fb\u002Fg' replaces literal \"a+\" (BRE — + is literal)\n# PRODUCTION: sed -E 's\u002Fa+\u002Fb\u002Fg' replaces \"one or more a\" (ERE)\nsed -E 's\u002Fa+\u002Fb\u002Fg' file              # ERE (extended regex)\n",[23,592,593,598,603],{"__ignoreMap":74},[78,594,595],{"class":80,"line":81},[78,596,597],{"class":84},"# NAIVE: sed 's\u002Fa+\u002Fb\u002Fg' replaces literal \"a+\" (BRE — + is literal)\n",[78,599,600],{"class":80,"line":88},[78,601,602],{"class":84},"# PRODUCTION: sed -E 's\u002Fa+\u002Fb\u002Fg' replaces \"one or more a\" (ERE)\n",[78,604,605,607,609,612,614],{"class":80,"line":94},[78,606,29],{"class":97},[78,608,258],{"class":119},[78,610,611],{"class":100}," 's\u002Fa+\u002Fb\u002Fg'",[78,613,264],{"class":100},[78,615,616],{"class":84},"              # ERE (extended regex)\n",[50,618,620,622],{"id":619},"awk-field-processing",[23,621,32],{}," — Field Processing",[14,624,625,627,628,26,631,634,635,638],{},[23,626,32],{}," is a full programming language for column-based text processing. It auto-splits each line into fields (",[23,629,630],{},"$1",[23,632,633],{},"$2",", ..., ",[23,636,637],{},"$0"," = whole line). Default field separator is whitespace.",[362,640,642],{"id":641},"complex-implementation-log-analysis-with-awk","Complex Implementation: Log Analysis with awk",[66,644,645],{"language":68},[70,646,648],{"className":72,"code":647,"language":68,"meta":74,"style":74},"# Sum HTTP status codes from an access log\nawk -F'\"' '{print $3}' access.log | awk '{print $1}' | sort | uniq -c | sort -rn\n#  1243 200\n#   872 404\n#    15 500\n\n# Top 10 requesting IPs with their request counts\nawk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10\n\n# Total bandwidth (bytes transferred = field 10 in Common Log Format)\nawk '{sum += $10} END{printf \"Total: %.2f MB\\n\", sum\u002F1024\u002F1024}' access.log\n\n# Users with bash shell (field 7 in \u002Fetc\u002Fpasswd)\nawk -F: '$7 ~ \u002Fbash$\u002F {print $1}' \u002Fetc\u002Fpasswd\n\n# Average of column 2\nawk '{sum += $2} END{print sum\u002FNR}' file\n",[23,649,650,655,694,699,704,709,713,718,748,752,757,767,771,777,791,796,802],{"__ignoreMap":74},[78,651,652],{"class":80,"line":81},[78,653,654],{"class":84},"# Sum HTTP status codes from an access log\n",[78,656,657,659,662,665,668,670,672,675,677,679,681,683,685,687,689,691],{"class":80,"line":88},[78,658,32],{"class":97},[78,660,661],{"class":119}," -F",[78,663,664],{"class":100},"'\"'",[78,666,667],{"class":100}," '{print $3}'",[78,669,357],{"class":100},[78,671,108],{"class":107},[78,673,674],{"class":97}," awk",[78,676,101],{"class":100},[78,678,108],{"class":107},[78,680,111],{"class":97},[78,682,108],{"class":107},[78,684,116],{"class":97},[78,686,120],{"class":119},[78,688,108],{"class":107},[78,690,111],{"class":97},[78,692,693],{"class":119}," -rn\n",[78,695,696],{"class":80,"line":94},[78,697,698],{"class":84},"#  1243 200\n",[78,700,701],{"class":80,"line":138},[78,702,703],{"class":84},"#   872 404\n",[78,705,706],{"class":80,"line":144},[78,707,708],{"class":84},"#    15 500\n",[78,710,711],{"class":80,"line":239},[78,712,396],{"emptyLinePlaceholder":395},[78,714,715],{"class":80,"line":253},[78,716,717],{"class":84},"# Top 10 requesting IPs with their request counts\n",[78,719,720,722,724,726,728,730,732,734,736,738,740,742,744,746],{"class":80,"line":270},[78,721,32],{"class":97},[78,723,101],{"class":100},[78,725,357],{"class":100},[78,727,108],{"class":107},[78,729,111],{"class":97},[78,731,108],{"class":107},[78,733,116],{"class":97},[78,735,120],{"class":119},[78,737,108],{"class":107},[78,739,111],{"class":97},[78,741,127],{"class":119},[78,743,108],{"class":107},[78,745,132],{"class":97},[78,747,135],{"class":119},[78,749,750],{"class":80,"line":286},[78,751,396],{"emptyLinePlaceholder":395},[78,753,754],{"class":80,"line":310},[78,755,756],{"class":84},"# Total bandwidth (bytes transferred = field 10 in Common Log Format)\n",[78,758,759,761,764],{"class":80,"line":330},[78,760,32],{"class":97},[78,762,763],{"class":100}," '{sum += $10} END{printf \"Total: %.2f MB\\n\", sum\u002F1024\u002F1024}'",[78,765,766],{"class":100}," access.log\n",[78,768,769],{"class":80,"line":346},[78,770,396],{"emptyLinePlaceholder":395},[78,772,774],{"class":80,"line":773},13,[78,775,776],{"class":84},"# Users with bash shell (field 7 in \u002Fetc\u002Fpasswd)\n",[78,778,780,782,785,788],{"class":80,"line":779},14,[78,781,32],{"class":97},[78,783,784],{"class":119}," -F:",[78,786,787],{"class":100}," '$7 ~ \u002Fbash$\u002F {print $1}'",[78,789,790],{"class":100}," \u002Fetc\u002Fpasswd\n",[78,792,794],{"class":80,"line":793},15,[78,795,396],{"emptyLinePlaceholder":395},[78,797,799],{"class":80,"line":798},16,[78,800,801],{"class":84},"# Average of column 2\n",[78,803,805,807,810],{"class":80,"line":804},17,[78,806,32],{"class":97},[78,808,809],{"class":100}," '{sum += $2} END{print sum\u002FNR}'",[78,811,812],{"class":100}," file\n",[362,814,816],{"id":815},"begin-end-blocks","BEGIN \u002F END Blocks",[66,818,819],{"language":68},[70,820,822],{"className":72,"code":821,"language":68,"meta":74,"style":74},"# Print header + data + footer\nawk -F: 'BEGIN{print \"User\\tUID\\tShell\"} {print $1\"\\t\"$3\"\\t\"$7} END{print \"Total: \" NR \" users\"}' \u002Fetc\u002Fpasswd\n",[23,823,824,829],{"__ignoreMap":74},[78,825,826],{"class":80,"line":81},[78,827,828],{"class":84},"# Print header + data + footer\n",[78,830,831,833,835,838],{"class":80,"line":88},[78,832,32],{"class":97},[78,834,784],{"class":119},[78,836,837],{"class":100}," 'BEGIN{print \"User\\tUID\\tShell\"} {print $1\"\\t\"$3\"\\t\"$7} END{print \"Total: \" NR \" users\"}'",[78,839,790],{"class":100},[50,841,843,845],{"id":842},"sort-sort-lines",[23,844,38],{}," — Sort Lines",[66,847,848],{"language":68},[70,849,851],{"className":72,"code":850,"language":68,"meta":74,"style":74},"sort -n file              # numeric (10 after 9, not after 1)\nsort -rn file             # numeric reverse (top values first)\nsort -u file              # sort + unique (dedupe)\nsort -k2 -n file          # sort by field 2, numeric\nsort -t: -k3 -n \u002Fetc\u002Fpasswd   # colon-delimited, sort by UID (field 3)\nsort -h file              # human-numeric (2K, 1M, 3G — for sizes)\nsort -V file              # version sort (v1.2.10 after v1.2.9)\n",[23,852,853,864,875,887,901,918,930],{"__ignoreMap":74},[78,854,855,857,859,861],{"class":80,"line":81},[78,856,38],{"class":97},[78,858,228],{"class":119},[78,860,264],{"class":100},[78,862,863],{"class":84},"              # numeric (10 after 9, not after 1)\n",[78,865,866,868,870,872],{"class":80,"line":88},[78,867,38],{"class":97},[78,869,127],{"class":119},[78,871,264],{"class":100},[78,873,874],{"class":84},"             # numeric reverse (top values first)\n",[78,876,877,879,882,884],{"class":80,"line":94},[78,878,38],{"class":97},[78,880,881],{"class":119}," -u",[78,883,264],{"class":100},[78,885,886],{"class":84},"              # sort + unique (dedupe)\n",[78,888,889,891,894,896,898],{"class":80,"line":138},[78,890,38],{"class":97},[78,892,893],{"class":119}," -k2",[78,895,228],{"class":119},[78,897,264],{"class":100},[78,899,900],{"class":84},"          # sort by field 2, numeric\n",[78,902,903,905,908,911,913,915],{"class":80,"line":144},[78,904,38],{"class":97},[78,906,907],{"class":119}," -t:",[78,909,910],{"class":119}," -k3",[78,912,228],{"class":119},[78,914,170],{"class":100},[78,916,917],{"class":84},"   # colon-delimited, sort by UID (field 3)\n",[78,919,920,922,925,927],{"class":80,"line":239},[78,921,38],{"class":97},[78,923,924],{"class":119}," -h",[78,926,264],{"class":100},[78,928,929],{"class":84},"              # human-numeric (2K, 1M, 3G — for sizes)\n",[78,931,932,934,937,939],{"class":80,"line":253},[78,933,38],{"class":97},[78,935,936],{"class":119}," -V",[78,938,264],{"class":100},[78,940,941],{"class":84},"              # version sort (v1.2.10 after v1.2.9)\n",[362,943,582,945,947],{"id":944},"edge-case-sort-is-locale-aware",[23,946,38],{}," is Locale-Aware",[66,949,950],{"language":68},[70,951,953],{"className":72,"code":952,"language":68,"meta":74,"style":74},"# NAIVE: locale-dependent sort (different order on different machines)\nsort file\n# In en_US.UTF-8, uppercase sorts differently than in C locale\n\n# PRODUCTION: byte-order sort (consistent across systems)\nLC_ALL=C sort file\n",[23,954,955,960,966,971,975,980],{"__ignoreMap":74},[78,956,957],{"class":80,"line":81},[78,958,959],{"class":84},"# NAIVE: locale-dependent sort (different order on different machines)\n",[78,961,962,964],{"class":80,"line":88},[78,963,38],{"class":97},[78,965,812],{"class":100},[78,967,968],{"class":80,"line":94},[78,969,970],{"class":84},"# In en_US.UTF-8, uppercase sorts differently than in C locale\n",[78,972,973],{"class":80,"line":138},[78,974,396],{"emptyLinePlaceholder":395},[78,976,977],{"class":80,"line":144},[78,978,979],{"class":84},"# PRODUCTION: byte-order sort (consistent across systems)\n",[78,981,982,984,986,988,990],{"class":80,"line":239},[78,983,407],{"class":406},[78,985,410],{"class":107},[78,987,413],{"class":100},[78,989,111],{"class":97},[78,991,812],{"class":100},[50,993,995,997],{"id":994},"uniq-deduplicate-adjacent-lines",[23,996,41],{}," — Deduplicate Adjacent Lines",[14,999,1000,1002,1003,1006,1007,64],{},[23,1001,41],{}," only removes ",[18,1004,1005],{},"adjacent"," duplicates. Usually preceded by ",[23,1008,38],{},[66,1010,1011],{"language":68},[70,1012,1014],{"className":72,"code":1013,"language":68,"meta":74,"style":74},"# Complex Implementation: frequency counter (the most reused pipeline in Linux)\nsort file | uniq -c | sort -rn    # count occurrences, sorted by frequency\n\n# Edge Case: uniq without sort appears to do nothing\n# NAIVE:\nuniq file                         # only removes adjacent dups — a\\nb\\na → all 3 lines\n# PRODUCTION:\nsort file | uniq                  # dedupe correctly (sort first)\n",[23,1015,1016,1021,1042,1046,1051,1056,1065,1070],{"__ignoreMap":74},[78,1017,1018],{"class":80,"line":81},[78,1019,1020],{"class":84},"# Complex Implementation: frequency counter (the most reused pipeline in Linux)\n",[78,1022,1023,1025,1027,1029,1031,1033,1035,1037,1039],{"class":80,"line":88},[78,1024,38],{"class":97},[78,1026,264],{"class":100},[78,1028,108],{"class":107},[78,1030,116],{"class":97},[78,1032,120],{"class":119},[78,1034,108],{"class":107},[78,1036,111],{"class":97},[78,1038,127],{"class":119},[78,1040,1041],{"class":84},"    # count occurrences, sorted by frequency\n",[78,1043,1044],{"class":80,"line":94},[78,1045,396],{"emptyLinePlaceholder":395},[78,1047,1048],{"class":80,"line":138},[78,1049,1050],{"class":84},"# Edge Case: uniq without sort appears to do nothing\n",[78,1052,1053],{"class":80,"line":144},[78,1054,1055],{"class":84},"# NAIVE:\n",[78,1057,1058,1060,1062],{"class":80,"line":239},[78,1059,41],{"class":97},[78,1061,264],{"class":100},[78,1063,1064],{"class":84},"                         # only removes adjacent dups — a\\nb\\na → all 3 lines\n",[78,1066,1067],{"class":80,"line":253},[78,1068,1069],{"class":84},"# PRODUCTION:\n",[78,1071,1072,1074,1076,1078,1080],{"class":80,"line":270},[78,1073,38],{"class":97},[78,1075,264],{"class":100},[78,1077,108],{"class":107},[78,1079,116],{"class":97},[78,1081,1082],{"class":84},"                  # dedupe correctly (sort first)\n",[50,1084,1086,1088],{"id":1085},"tr-transliterate-delete",[23,1087,44],{}," — Transliterate \u002F Delete",[14,1090,1091,1093,1094,1097],{},[23,1092,44],{}," works on ",[18,1095,1096],{},"characters",", not lines:",[66,1099,1100],{"language":68},[70,1101,1103],{"className":72,"code":1102,"language":68,"meta":74,"style":74},"echo \"Hello\" | tr 'a-z' 'A-Z'             # HELLO (uppercase)\necho \"hello  world\" | tr -s ' '           # hello world (squeeze repeats)\necho \"hello world\" | tr -cd 'a-zA-Z'      # helloworld (delete non-alpha)\necho \"1,2,3\" | tr ',' '\\n'               # split CSV into lines\n",[23,1104,1105,1127,1147,1167],{"__ignoreMap":74},[78,1106,1107,1110,1113,1115,1118,1121,1124],{"class":80,"line":81},[78,1108,1109],{"class":119},"echo",[78,1111,1112],{"class":100}," \"Hello\"",[78,1114,108],{"class":107},[78,1116,1117],{"class":97}," tr",[78,1119,1120],{"class":100}," 'a-z'",[78,1122,1123],{"class":100}," 'A-Z'",[78,1125,1126],{"class":84},"             # HELLO (uppercase)\n",[78,1128,1129,1131,1134,1136,1138,1141,1144],{"class":80,"line":88},[78,1130,1109],{"class":119},[78,1132,1133],{"class":100}," \"hello  world\"",[78,1135,108],{"class":107},[78,1137,1117],{"class":97},[78,1139,1140],{"class":119}," -s",[78,1142,1143],{"class":100}," ' '",[78,1145,1146],{"class":84},"           # hello world (squeeze repeats)\n",[78,1148,1149,1151,1154,1156,1158,1161,1164],{"class":80,"line":94},[78,1150,1109],{"class":119},[78,1152,1153],{"class":100}," \"hello world\"",[78,1155,108],{"class":107},[78,1157,1117],{"class":97},[78,1159,1160],{"class":119}," -cd",[78,1162,1163],{"class":100}," 'a-zA-Z'",[78,1165,1166],{"class":84},"      # helloworld (delete non-alpha)\n",[78,1168,1169,1171,1174,1176,1178,1181,1184],{"class":80,"line":138},[78,1170,1109],{"class":119},[78,1172,1173],{"class":100}," \"1,2,3\"",[78,1175,108],{"class":107},[78,1177,1117],{"class":97},[78,1179,1180],{"class":100}," ','",[78,1182,1183],{"class":100}," '\\n'",[78,1185,1186],{"class":84},"               # split CSV into lines\n",[50,1188,1190,1192],{"id":1189},"xargs-build-command-lines-from-stdin",[23,1191,47],{}," — Build Command Lines from Stdin",[66,1194,1195],{"language":68},[70,1196,1198],{"className":72,"code":1197,"language":68,"meta":74,"style":74},"# Complex Implementation: null-delimited pipeline (safe for any filename)\n# — filenames can contain spaces, newlines, and quotes\nfind . -type f -print0 | xargs -0 grep \"pattern\"\n#  -print0: separate filenames with NUL (\\0), not newline\n#  -0:      xargs reads NUL-delimited input\n\n# Anti-Pattern: newline-delimited (breaks on filenames with spaces)\n# find . -name \"*.txt\" | xargs grep foo   → breaks on \"my notes.txt\"\n\n# Prefer -exec {} + (equivalent safety, no xargs needed):\nfind . -type f -name \"*.txt\" -exec grep \"pattern\" {} +\n",[23,1199,1200,1205,1210,1240,1245,1250,1254,1259,1264,1268,1273],{"__ignoreMap":74},[78,1201,1202],{"class":80,"line":81},[78,1203,1204],{"class":84},"# Complex Implementation: null-delimited pipeline (safe for any filename)\n",[78,1206,1207],{"class":80,"line":88},[78,1208,1209],{"class":84},"# — filenames can contain spaces, newlines, and quotes\n",[78,1211,1212,1215,1218,1221,1224,1227,1229,1232,1235,1237],{"class":80,"line":94},[78,1213,1214],{"class":97},"find",[78,1216,1217],{"class":100}," .",[78,1219,1220],{"class":119}," -type",[78,1222,1223],{"class":100}," f",[78,1225,1226],{"class":119}," -print0",[78,1228,108],{"class":107},[78,1230,1231],{"class":97}," xargs",[78,1233,1234],{"class":119}," -0",[78,1236,416],{"class":100},[78,1238,1239],{"class":100}," \"pattern\"\n",[78,1241,1242],{"class":80,"line":138},[78,1243,1244],{"class":84},"#  -print0: separate filenames with NUL (\\0), not newline\n",[78,1246,1247],{"class":80,"line":144},[78,1248,1249],{"class":84},"#  -0:      xargs reads NUL-delimited input\n",[78,1251,1252],{"class":80,"line":239},[78,1253,396],{"emptyLinePlaceholder":395},[78,1255,1256],{"class":80,"line":253},[78,1257,1258],{"class":84},"# Anti-Pattern: newline-delimited (breaks on filenames with spaces)\n",[78,1260,1261],{"class":80,"line":270},[78,1262,1263],{"class":84},"# find . -name \"*.txt\" | xargs grep foo   → breaks on \"my notes.txt\"\n",[78,1265,1266],{"class":80,"line":286},[78,1267,396],{"emptyLinePlaceholder":395},[78,1269,1270],{"class":80,"line":310},[78,1271,1272],{"class":84},"# Prefer -exec {} + (equivalent safety, no xargs needed):\n",[78,1274,1275,1277,1279,1281,1283,1286,1289,1292,1294,1297,1300],{"class":80,"line":330},[78,1276,1214],{"class":97},[78,1278,1217],{"class":100},[78,1280,1220],{"class":119},[78,1282,1223],{"class":100},[78,1284,1285],{"class":119}," -name",[78,1287,1288],{"class":100}," \"*.txt\"",[78,1290,1291],{"class":119}," -exec",[78,1293,416],{"class":100},[78,1295,1296],{"class":100}," \"pattern\"",[78,1298,1299],{"class":100}," {}",[78,1301,1302],{"class":100}," +\n",[50,1304,1306],{"id":1305},"composing-pipelines-real-world-examples","Composing Pipelines — Real-World Examples",[362,1308,1310],{"id":1309},"extract-all-urls-from-a-log","Extract All URLs from a Log",[66,1312,1313],{"language":68},[70,1314,1316],{"className":72,"code":1315,"language":68,"meta":74,"style":74},"grep -oE 'https?:\u002F\u002F[^ ]+' \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log | sort -u\n",[23,1317,1318],{"__ignoreMap":74},[78,1319,1320,1322,1324,1326,1328,1330,1332],{"class":80,"line":81},[78,1321,25],{"class":97},[78,1323,351],{"class":119},[78,1325,354],{"class":100},[78,1327,104],{"class":100},[78,1329,108],{"class":107},[78,1331,111],{"class":97},[78,1333,1334],{"class":119}," -u\n",[362,1336,1338],{"id":1337},"count-files-per-extension","Count Files per Extension",[66,1340,1341],{"language":68},[70,1342,1344],{"className":72,"code":1343,"language":68,"meta":74,"style":74},"find . -type f | sed 's\u002F.*\\.\u002F\u002F' | sort | uniq -c | sort -rn\n",[23,1345,1346],{"__ignoreMap":74},[78,1347,1348,1350,1352,1354,1356,1358,1361,1364,1366,1368,1370,1372,1374,1376,1378],{"class":80,"line":81},[78,1349,1214],{"class":97},[78,1351,1217],{"class":100},[78,1353,1220],{"class":119},[78,1355,1223],{"class":100},[78,1357,108],{"class":107},[78,1359,1360],{"class":97}," sed",[78,1362,1363],{"class":100}," 's\u002F.*\\.\u002F\u002F'",[78,1365,108],{"class":107},[78,1367,111],{"class":97},[78,1369,108],{"class":107},[78,1371,116],{"class":97},[78,1373,120],{"class":119},[78,1375,108],{"class":107},[78,1377,111],{"class":97},[78,1379,693],{"class":119},[362,1381,1383],{"id":1382},"show-process-tree-of-a-service","Show Process Tree of a Service",[66,1385,1386],{"language":68},[70,1387,1389],{"className":72,"code":1388,"language":68,"meta":74,"style":74},"ps aux | grep nginx | grep -v grep | awk '{print $2}' | head -1 | xargs -I{} pstree -p {}\n",[23,1390,1391],{"__ignoreMap":74},[78,1392,1393,1396,1399,1401,1403,1406,1408,1410,1412,1414,1416,1418,1421,1423,1425,1428,1430,1432,1435],{"class":80,"line":81},[78,1394,1395],{"class":97},"ps",[78,1397,1398],{"class":100}," aux",[78,1400,108],{"class":107},[78,1402,416],{"class":97},[78,1404,1405],{"class":100}," nginx",[78,1407,108],{"class":107},[78,1409,416],{"class":97},[78,1411,212],{"class":119},[78,1413,416],{"class":100},[78,1415,108],{"class":107},[78,1417,674],{"class":97},[78,1419,1420],{"class":100}," '{print $2}'",[78,1422,108],{"class":107},[78,1424,132],{"class":97},[78,1426,1427],{"class":119}," -1",[78,1429,108],{"class":107},[78,1431,1231],{"class":97},[78,1433,1434],{"class":119}," -I",[78,1436,1437],{"class":406},"{} pstree -p {}\n",[50,1439,1441],{"id":1440},"tips-tricks","💡 Tips & Tricks",[1443,1444,1445,1456,1468,1484,1503,1521],"ul",{},[1446,1447,1448,1451,1452,1455],"li",{},[18,1449,1450],{},"Idiom",": use ",[23,1453,1454],{},"sort | uniq -c | sort -rn"," as a frequency counter — the most reused pipeline in Linux. Counts how many times each line appears, sorted by frequency.",[1446,1457,1458,1451,1460,1463,1464,1467],{},[18,1459,1450],{},[23,1461,1462],{},"awk '{print $NF}'"," for the last field — ",[23,1465,1466],{},"$NF"," is \"field number NF\" (the count), so it's always the last field regardless of how many fields the line has.",[1446,1469,1470,1451,1472,1475,1476,1479,1480,1483],{},[18,1471,1450],{},[23,1473,1474],{},"tail -F"," (capital) instead of ",[23,1477,1478],{},"tail -f"," for log watching — ",[23,1481,1482],{},"-F"," handles log rotation (re-opens if the file is moved\u002Frecreated).",[1446,1485,1486,1451,1488,1491,1492,1494,1495,1498,1499,1502],{},[18,1487,1450],{},[23,1489,1490],{},"grep -E"," for readability over ",[23,1493,25],{}," with backslashes — ",[23,1496,1497],{},"grep -E \"cat|dog\""," is clearer than ",[23,1500,1501],{},"grep \"cat\\|dog\"",".",[1446,1504,1505,1508,1509,1511,1512,1514,1515,1517,1518,1520],{},[18,1506,1507],{},"Performance",": ",[23,1510,25],{}," is faster than ",[23,1513,32],{}," for plain matching — use ",[23,1516,25],{}," for filtering, ",[23,1519,32],{}," when you need field logic.",[1446,1522,1523,1508,1525,1528,1529,1532,1533,1536],{},[18,1524,1507],{},[23,1526,1527],{},"sort -S 50% --parallel=4"," speeds up large sorts — ",[23,1530,1531],{},"-S"," sets buffer size (50% of RAM), ",[23,1534,1535],{},"--parallel"," uses multiple cores.",[50,1538,1540],{"id":1539},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[1443,1542,1543,1560,1579,1601,1618,1638,1659,1675],{},[1446,1544,1545,1508,1550,1553,1554,1556,1557,1559],{},[18,1546,1547,1549],{},[23,1548,41],{}," only removes adjacent duplicates",[23,1551,1552],{},"echo -e \"a\\nb\\na\" | uniq"," outputs all three lines. Always ",[23,1555,38],{}," before ",[23,1558,41],{}," unless you specifically want adjacent-only dedup.",[1446,1561,1562,1508,1568,1571,1572,1575,1576,1502],{},[18,1563,1564,1567],{},[23,1565,1566],{},"sed -i"," has no undo",[23,1569,1570],{},"sed -i 's\u002Fold\u002Fnew\u002Fg' file"," overwrites the file. If your regex is wrong, the file is corrupted. Always test without ",[23,1573,1574],{},"-i"," first, or use ",[23,1577,1578],{},"sed -i.bak",[1446,1580,1581,1508,1586,1589,1590,1593,1594,1597,1598,1502],{},[18,1582,1583,1584],{},"Filenames with spaces break ",[23,1585,47],{},[23,1587,1588],{},"find . -name \"*.txt\" | xargs grep foo"," fails on ",[23,1591,1592],{},"my notes.txt",". Use ",[23,1595,1596],{},"find -print0 | xargs -0"," or ",[23,1599,1600],{},"find -exec {} +",[1446,1602,1603,1508,1608,1610,1611,1614,1615,1502],{},[18,1604,1605,1607],{},[23,1606,38],{}," is locale-aware",[23,1609,38],{}," uses your locale (",[23,1612,1613],{},"LC_COLLATE","). For byte-order sorting (consistent across systems), use ",[23,1616,1617],{},"LC_ALL=C sort",[1446,1619,1620,1629,1630,1632,1633,1635,1636,1502],{},[18,1621,1622,1625,1626],{},[23,1623,1624],{},"grep -r"," vs ",[23,1627,1628],{},"-R",": GNU ",[23,1631,1624],{}," does NOT follow symlinks; ",[23,1634,1628],{}," does. Watch for symlink loops with ",[23,1637,1628],{},[1446,1639,1640,1508,1645,1648,1649,1651,1652,1593,1655,1658],{},[18,1641,1642,1644],{},[23,1643,32],{}," treats numbers as strings sometimes",[23,1646,1647],{},"awk '$1 > 10'"," may do string comparison if ",[23,1650,630],{}," is ",[23,1653,1654],{},"\"9abc\"",[23,1656,1657],{},"awk '$1 + 0 > 10'"," to force numeric.",[1446,1660,1661,1508,1667,1670,1671,1674],{},[18,1662,1663,1666],{},[23,1664,1665],{},"cut -d\" \""," treats consecutive spaces as multiple empty fields",[23,1668,1669],{},"echo \"a  b\" | cut -d\" \" -f2"," gives empty. Use ",[23,1672,1673],{},"awk '{print $2}'"," instead (awk treats consecutive whitespace as one separator).",[1446,1676,1677,1508,1680,1683,1684,1687,1688,1691,1692,1695,1696,1698,1699,1702],{},[18,1678,1679],{},"Pipelines hide intermediate failures",[23,1681,1682],{},"cmd1 | cmd2 | cmd3"," — if ",[23,1685,1686],{},"cmd1"," fails, ",[23,1689,1690],{},"cmd2"," and ",[23,1693,1694],{},"cmd3"," still run. The pipeline's exit status is ",[23,1697,1694],{},"'s. Use ",[23,1700,1701],{},"set -o pipefail"," in scripts.",[50,1704,1706],{"id":1705},"spot-the-bug","🧠 Spot the Bug",[14,1708,1709],{},"A sysadmin wants to count how many times each error code appears in a log, but this pipeline gives wrong counts — many error codes show count 1 that should be higher:",[66,1711,1712],{"language":68},[70,1713,1715],{"className":72,"code":1714,"language":68,"meta":74,"style":74},"grep \"ERROR\" app.log | awk '{print $4}' | uniq -c | sort -rn | head\n",[23,1716,1717],{"__ignoreMap":74},[78,1718,1719,1721,1724,1726,1728,1730,1733,1735,1737,1739,1741,1743,1745,1747],{"class":80,"line":81},[78,1720,25],{"class":97},[78,1722,1723],{"class":100}," \"ERROR\"",[78,1725,218],{"class":100},[78,1727,108],{"class":107},[78,1729,674],{"class":97},[78,1731,1732],{"class":100}," '{print $4}'",[78,1734,108],{"class":107},[78,1736,116],{"class":97},[78,1738,120],{"class":119},[78,1740,108],{"class":107},[78,1742,111],{"class":97},[78,1744,127],{"class":119},[78,1746,108],{"class":107},[78,1748,1749],{"class":97}," head\n",[14,1751,1752],{},"What's wrong, and how do you fix it?",[1754,1755,1756,1760,1779,1814,1823,1864,1873],"details",{},[1757,1758,1759],"summary",{},"Answer",[14,1761,1762,1767,1768,1770,1771,1774,1775,1778],{},[18,1763,1764,1766],{},[23,1765,41],{}," only deduplicates adjacent duplicates."," The error codes from ",[23,1769,32],{}," are in log order (not sorted), so ",[23,1772,1773],{},"E404 E500 E404 E404 E500"," has no adjacent duplicates collapsed — ",[23,1776,1777],{},"uniq -c"," reports each run separately:",[66,1780,1781],{"language":68},[70,1782,1784],{"className":72,"code":1783,"language":68,"meta":74,"style":74},"1 E404\n1 E500\n2 E404\n1 E500\n",[23,1785,1786,1794,1801,1808],{"__ignoreMap":74},[78,1787,1788,1791],{"class":80,"line":81},[78,1789,1790],{"class":97},"1",[78,1792,1793],{"class":100}," E404\n",[78,1795,1796,1798],{"class":80,"line":88},[78,1797,1790],{"class":97},[78,1799,1800],{"class":100}," E500\n",[78,1802,1803,1806],{"class":80,"line":94},[78,1804,1805],{"class":97},"2",[78,1807,1793],{"class":100},[78,1809,1810,1812],{"class":80,"line":138},[78,1811,1790],{"class":97},[78,1813,1800],{"class":100},[14,1815,1816],{},[18,1817,1818,1819,1556,1821,64],{},"Fix: ",[23,1820,38],{},[23,1822,41],{},[66,1824,1825],{"language":68},[70,1826,1828],{"className":72,"code":1827,"language":68,"meta":74,"style":74},"grep \"ERROR\" app.log | awk '{print $4}' | sort | uniq -c | sort -rn | head\n",[23,1829,1830],{"__ignoreMap":74},[78,1831,1832,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852,1854,1856,1858,1860,1862],{"class":80,"line":81},[78,1833,25],{"class":97},[78,1835,1723],{"class":100},[78,1837,218],{"class":100},[78,1839,108],{"class":107},[78,1841,674],{"class":97},[78,1843,1732],{"class":100},[78,1845,108],{"class":107},[78,1847,111],{"class":97},[78,1849,108],{"class":107},[78,1851,116],{"class":97},[78,1853,120],{"class":119},[78,1855,108],{"class":107},[78,1857,111],{"class":97},[78,1859,127],{"class":119},[78,1861,108],{"class":107},[78,1863,1749],{"class":97},[14,1865,1866,1867,1869,1870,1872],{},"Now ",[23,1868,38],{}," groups identical codes together, and ",[23,1871,1777],{}," counts each group correctly:",[66,1874,1875],{"language":68},[70,1876,1878],{"className":72,"code":1877,"language":68,"meta":74,"style":74},"3 E404\n2 E500\n",[23,1879,1880,1887],{"__ignoreMap":74},[78,1881,1882,1885],{"class":80,"line":81},[78,1883,1884],{"class":97},"3",[78,1886,1793],{"class":100},[78,1888,1889,1891],{"class":80,"line":88},[78,1890,1805],{"class":97},[78,1892,1800],{"class":100},[1894,1895,1896],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}",{"title":74,"searchDepth":88,"depth":88,"links":1898},[1899,1900,1905,1912,1917,1922,1924,1926,1928,1933,1934,1935],{"id":52,"depth":88,"text":53},{"id":150,"depth":88,"text":1901,"children":1902},"grep — Search",[1903],{"id":364,"depth":94,"text":1904},"Performance Tip: LC_ALL=C grep for Huge Files",{"id":428,"depth":88,"text":1906,"children":1907},"sed — Stream Editor",[1908,1909,1910],{"id":434,"depth":94,"text":435},{"id":517,"depth":94,"text":518},{"id":581,"depth":94,"text":1911},"Edge Case: sed Regex is BRE by Default",{"id":619,"depth":88,"text":1913,"children":1914},"awk — Field Processing",[1915,1916],{"id":641,"depth":94,"text":642},{"id":815,"depth":94,"text":816},{"id":842,"depth":88,"text":1918,"children":1919},"sort — Sort Lines",[1920],{"id":944,"depth":94,"text":1921},"Edge Case: sort is Locale-Aware",{"id":994,"depth":88,"text":1923},"uniq — Deduplicate Adjacent Lines",{"id":1085,"depth":88,"text":1925},"tr — Transliterate \u002F Delete",{"id":1189,"depth":88,"text":1927},"xargs — Build Command Lines from Stdin",{"id":1305,"depth":88,"text":1306,"children":1929},[1930,1931,1932],{"id":1309,"depth":94,"text":1310},{"id":1337,"depth":94,"text":1338},{"id":1382,"depth":94,"text":1383},{"id":1440,"depth":88,"text":1441},{"id":1539,"depth":88,"text":1540},{"id":1705,"depth":88,"text":1706},"Linux philosophy: write small tools that do one thing well, then combine them with pipes. This chapter covers the core text-processing toolkit — grep, sed, awk, cut, sort, uniq, tr, xargs — composed into production-grade one-liners. This is arguably the most important skill for a Linux engineer.","md",{},"\u002Flinux\u002F05-text-processing",{"title":5,"description":1936},"linux\u002F05-text-processing","BWC4y1pieMopQhUH6J2ZEX55zhYhkKHkVxgBQDjo6hM",1789924649859]