【问题标题】:Need To Print Backslash When Preparing mysql statement准备mysql语句时需要打印反斜杠
【发布时间】:2016-10-07 05:44:21
【问题描述】:

我有一个文件需要转换成mysql插入语句,格式如下:

1
'Jan'
'Jame'
'O\'Leary'
'Bill'
''
NULL
1
'Eddie'
'Eddie'
'Unknown'
NULL
NULL
'John'
NULL
'Joseph'

我正在尝试使用以下代码来准备语句:

COUNTER=1;
echo "insert into database.table values " > full_statements.sql

while read LINE
do
    # There are 16 fields of information per insert statement.
    MODULUS=$(( $COUNTER % 16 ))
    # First piece of information needs to be in format "(value"
    if [ "$COUNTER" -eq 1 ]; then
        printf "("$LINE >> full_statements.sql
    # Last piece of information needs to be in format ",value),"        
    elif [ "$MODULUS" -eq 0 ]; then
        printf ","$LINE")," >> full_statements.sql
    # Interior pieces of information need to be in format ",value"
    else
        printf ","$LINE >> full_statements.sql
    fi

    # If we have a complete insert statement, reset the COUNTER.
    if [ "$COUNTER" -eq 16 ]; then
        COUNTER=1
    else
        ((COUNTER++))
    fi
done < binfile.new

不幸的是,我的结果如下:

insert into database.table values
(1,'Jan','Jame','O'Leary','Bill','',NULL,1,'Eddie','Eddie','Unknown',NULL,NULL,'John',NULL,'Joseph');

预期输出:

 insert into database.table values
    (1,'Jan','Jame','O\'Leary','Bill','',NULL,1,'Eddie','Eddie','Unknown',NULL,NULL,'John',NULL,'Joseph');

我用来转义 O'Leary 名字中的引号的反斜杠不会打印出来。我正在努力将这个“\”包含在输出中,但找不到答案。

帮助! :-)

【问题讨论】:

  • 不是答案,但请阅读:unix.stackexchange.com/questions/169716/…
  • 试试echo -e "insert into database.table values \n ( $(awk -vORS="," '{$1=$1}1' INPUTFILE) );" |sed 's/\(.*\),/\1/'
  • 另外,添加预期输出,以便其他人可以比较他们的解决方案...
  • PS,我不确定代码的位置——你能详细说明一下代码段吗?
  • 正确使用printfprintf '(%s' "$LINE" 可以帮助您解决问题。

标签: linux bash awk sed escaping


【解决方案1】:

在 awk 中。使用模 16 识别记录更改(即支持文件中超过 16 行)和三元运算符在内容之前和之后插入内容:

$ cat program.awk 
{
    printf "%s%s%s",(NR%16==1?"INSERT INTO DATABASE VALUES (":""),$0,(NR%16?",":");"ORS)
}

运行它:

$ awk -f program.awk file
INSERT INTO DATABASE VALUES (1,'Jan','Jame','O\'Leary','Bill','',NULL,1,'Eddie','Eddie','Unknown',NULL,NULL,'John',NULL,'Joseph');

【讨论】:

    【解决方案2】:

    来自help read

     -r       do not allow backslashes to escape any characters
    
    $ read foo <<< '12\3'
    $ echo "$foo"
    123
    $ read -r foo <<< '12\3'
    $ echo "$foo"
    12\3
    

    【讨论】:

      【解决方案3】:

      这感觉像是 pr 的任务

      假设输入文件包含 5 行,并且您希望每行按 2 个元素分组:

      $ seq 5 | pr -2ats, | sed 's/.*/\t(&);/'
          (1,2);
          (3,4);
          (5);
      
      • seq 5 5 行示例输入
      • pr -2ats, 最多打印 2 个由 , 分隔的字段
      • sed 's/.*/\t(&amp;)/' 后处理pr 输出以在文本周围添加(),在行尾添加;,在行前添加tab


      所以,最后对于你的用例,它会是这样的:

      $ ( echo 'insert into database.table values' ; pr -16ats, binfile.new | sed 's/.*/\t(&);/' ) > full_statements.sql
      

      【讨论】:

      • 警告意外令牌'echo'
      • 好的,好像你在命令的开头也添加了$ ..这意味着命令提示符而不是实际命令的一部分:)
      【解决方案4】:

      这应该更简单一些。除了重构之外,实际的解决方法是使用-r 选项和read 来防止输入中的反斜杠被解释。使用IFS= 是一种很好的做法,可以确保逐字阅读每一行,而不会删除任何前导或尾随空格。

      # It's easier to just hard-code the 16 %s rather than build it dynamically.
      fmt="insert into database.table values (
      %s, %s, %s, %s,
      %s, %s, %s, %s,
      %s, %s, %s, %s,
      %s, %s, %s, %s)\n"
      
      # Read 16 lines, putting each line in a global array
      # Return 1 if any read fails
      read16 () {
          values=()
          for ((i=0; i<16; i++)); do
              IFS= read -r line || return 1
              values+=("$line")
          done
      }
      
      declare -a values
      while read16; do
        printf "$fmt" "${values[@]}"
      done < binfile.new > full_statements.sql
      

      请注意,如果您将单引号放在格式字符串中:

      fmt="insert ... ('%s', '%s', ...)\n"
      

      那么您不需要将它们包含在数据文件中:

      1
      Jan
      Jame
      O'Leary
      Bill
      ...
      

      【讨论】:

        【解决方案5】:
        $ awk -v OFS=',' -v ORS=');\n' -v m=16 '{n=(NR-1)%m+1; f[n]=$0} n==m{printf "insert blah\n   ("; for (i=1;i<=m;i++) printf "%s%s", f[i], (i<m ? OFS : ORS)}' file
        insert blah
           (1,'Jan','Jame','O\'Leary','Bill','',NULL,1,'Eddie','Eddie','Unknown',NULL,NULL,'John',NULL,'Joseph');
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-05
          • 1970-01-01
          • 2019-01-13
          • 2015-08-27
          • 2013-11-10
          • 2017-03-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多